问:
Clang warning flags for Objective-C development
As a C & Objective-C programmer, I'm a bit paranoid with the compiler warning flags.

I usually try to find a complete list of warning flags for the compiler I use, and turn most of them on, unless I have a really good reason not to turn it on.

I personally think this may actually improve coding skills, as well as potential code portability, prevent some issues, as it forces you to be aware of every little detail, potential implementation and architecture issues, and so on...

It's also in my opinion a good every day learning tool, even if you're an experienced programmer.

For the subjective part of this question, I'm interested in hearing other developers (mainly C, Objective-C and C++) about this topic.

Do you actually care about stuff like pedantic warnings, etc? And if yes or no, why?

Now about Objective-C, I recently completely switched to the LLVM toolchain (with Clang), instead of GCC.

On my production code, I usually set this warning flags (explicitly, even if some of them may be covered by -Wall):

-Wall

-Wbad-function-cast

-Wcast-align

-Wconversion

-Wdeclaration-after-statement

-Wdeprecated-implementations

-Wextra

-Wfloat-equal

-Wformat=2

-Wformat-nonliteral

-Wfour-char-constants

-Wimplicit-atomic-properties

-Wmissing-braces

-Wmissing-declarations

-Wmissing-field-initializers

-Wmissing-format-attribute

-Wmissing-noreturn

-Wmissing-prototypes

-Wnested-externs

-Wnewline-eof

-Wold-style-definition

-Woverlength-strings

-Wparentheses

-Wpointer-arith

-Wredundant-decls

-Wreturn-type

-Wsequence-point

-Wshadow

-Wshorten-64-to-32

-Wsign-compare

-Wsign-conversion

-Wstrict-prototypes

-Wstrict-selector-match

-Wswitch

-Wswitch-default

-Wswitch-enum

-Wundeclared-selector

-Wuninitialized

-Wunknown-pragmas

-Wunreachable-code

-Wunused-function

-Wunused-label

-Wunused-parameter

-Wunused-value

-Wunused-variable

-Wwrite-strings

I'm interested in hearing what other developers have to say about this.

For instance, do you think I missed a particular flag for Clang (Objective-C), and why?

Or do you think a particular flag is not useful (or not wanted at all), and why?

EDIT

To clarify the question, note that -Wall only provides a few basic warnings.

They are actually a lot more warning flags, not covered by -Wall, hence the question, and the list I provide.

答:
For context, I'm a Clang developer working at Google. At Google, we've rolled
Clang's diagnostics out to (essentially) all of our C++ developers, and we
treat Clang's warnings as errors as well. As both a Clang developer and one of the larger users of Clang's diagnostics I'll try to shed some light on these flags and how they can be used. Note that everything I'm describing is generically applicable to Clang, and not specific to C, C++, or Objective-C.

TL;DR Version: Please use -Wall and -Werror at a minimum on any new code
you are developing. We (the compiler developers) add warnings here for good
reasons: they find bugs. If you find a warning that catches bugs for you, turn
it on as well. Try -Wextra for a bunch of good candidates here. If one of
them is too noisy for you to use profitably, file a bug. If you write code that
contains an "obvious" bug but the compiler didn't warn about it, file a bug.

Now for the long version. First some background on warning flag groupings.
There are a lot of "groupings" of warnings in Clang (and to a limited extent in
GCC). Some that are relevant to this discussion:

On-by-default: These warnings are always on unless you explicitly disable them.

-Wall: These are warnings that the developers have high confidence in
both their value and a low false-positive rate.

-Wextra: These are warnings that are believed to be valuable and sound
(i.e., they aren't buggy), but they may have high false-positive rates or
common philosophical objections.

-Weverything: This is an insane group that literally enables every
warning in Clang. Don't use this on your code. It is intended strictly for
Clang developers or for exploring what warnings exist.

There are two primary criteria mentioned above which guide where warnings go in
Clang, and let's clarify what these really mean. The first is the potential
value of a particular occurrence of the warning. This is the expected
benefit to the user (developer) when the warning fires and correctly
identifies an issue with the code.

The second criteria is the idea of false-positive reports. These are
situations where the warning fires on code, but the potential problem being
cited does not in fact occur due to the context or some other constraint of the
program. The code warned about is actually behaving correctly. These are
especially bad when the warning was never intended to fire on that code
pattern. Instead, it is a deficiency in the warning's implementation that causes
it to fire there.

For Clang warnings, the value is required to be in terms of correctness,
not in terms of style, taste, or coding conventions. This limits the set of
warnings available, precluding oft-requested warnings such as warning
whenever {}s are not used around the body of an if statement. Clang is also
very intolerant of false-positives. Unlike most other compilers it will use
an incredible variety of information sources to prune false positives including
the exact spelling of the construct, presence or absence of extra '()', casts,
or even preprocessor macros!

Now let's take some real-world example warnings from Clang, and look at how
they are categorized. First, a default-on warning:

```<code>% nl x.cc
     1  class C { const int x; };

% clang -fsyntax-only x.cc
x.cc:1:7: warning: class 'C' does not declare any constructor to initialize its non-modifiable members
class C { const int x; };
      ^
x.cc:1:21: note: const member 'x' will never be initialized
class C { const int x; };
                    ^
1 warning generated.
</code>```

Here no flag was required to get this warning. The rationale is that this is
code is never really correct, giving the warning high value, and the
warning only fires on code that Clang can prove falls into this bucket, giving
it a zero false-positive rate.

```<code>% nl x2.cc
     1  int f(int x_) {
     2    int x = x;
     3    return x;
     4  }

% clang -fsyntax-only -Wall x2.cc
x2.cc:2:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
  int x = x;
      ~   ^
1 warning generated.
</code>```

Clang requires the -Wall flag for this warning. The reason is that there is
a non-trivial amount of code out there which has used (for good or ill) the
code pattern we are warning about to intentionally produce an uninitialized
value. Philosophically, I see no point in this, but many others disagree and
the reality of this difference in opinion is what drives the warning under the
-Wall flag. It still has very high value and a very low
false-positive rate, but on some codebases it is a non-starter.

```<code>% nl x3.cc
     1  void g(int x);
     2  void f(int arr[], unsigned int size) {
     3    for (int i = 0; i < size; ++i)
     4      g(arr[i]);
     5  }

% clang -fsyntax-only -Wextra x3.cc
x3.cc:3:21: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
  for (int i = 0; i < size; ++i)
                  ~ ^ ~~~~
1 warning generated.
</code>```

This warning requires the -Wextra flag. The reason is that there are very
large codebases where mis-matched sign on comparisons is extremely common.
While this warning does find some bugs, the probability of the code being a bug
when the user writes it is fairly low on average. The result is an extremely
high false-positive rate. However, when there is a bug in a program due to
the strange promotion rules, it is often extremely subtle making this warning
when it flags a bug have relatively high value. As a consequence, Clang
provides it and exposes it under a flag.

Typically, warnings don't live long outside of the -Wextra flag. Clang tries
very hard to not implement warnings which do not see regular use and testing.
The additional warnings turned on by -Weverything are usually warnings under
active development or with active bugs. Either they will be fixed and placed
under appropriate flags, or they should be removed.

Now that we have an understanding of how these things work with Clang, let's
try to get back to the original question: what warnings should you turn on for
your development? The answer is, unfortunately, that it depends. Consider the
following questions to help determine what warnings work best for your
situation.

Do you have control over all of your code, or is some of it external?

What are your goals? Catching bugs, or writing better code?

What is your false-positive tolerance? Are you willing to write extra code
to silence warnings on a regular basis?

First and foremost, if you don't control the code, don't try turning extra
warnings on there. Be prepared to turn some off. There is a lot of bad code in
the world, and you may not be able to fix all of it. That is OK. Work to find a
way to focus your efforts on the code you control.

Next, figure out what you want out of your warnings. This is different for
different people. Clang will try to warn without any options on egregious bugs,
or code patterns for which we have long historical precedent indicating the bug
rate is extremely high. By enabling -Wall you're going to get a much more
aggressive set of warnings targeted at catching the most common mistakes that
Clang developers have observed in C++ code. But with both of these the
false-positive rate should remain quite low.

Finally, if you're perfectly willing to silence false-positives at every
turn, go for -Wextra. File bugs if you notice warnings which are catching
a lot of real bugs, but which have silly or pointless false positives. We're
constantly working to find ways to bring more and more of the bug-finding logic
present in -Wextra into -Wall where we can avoid the false-positives.

Many will find that none of these options is just-right for them. At Google,
we've turned some warnings in -Wall off due to a lot of existing code that
violated the warning. We've also turned some warnings on explicitly, even
though they aren't enabled by -Wall, because they have a particularly high
value to us. Your mileage will vary, but will likely vary in similar ways. It
can often be much better to enable a few key warnings rather than all of
-Wextra.

I would encourage everyone to turn on -Wall for any non-legacy code. For
new code, the warnings here are almost always valuable, and really make the
experience of developing code better. Conversely, I would encourage everyone to
not enable flags beyond -Wextra. If you find a Clang warning that -Wextra
doesn't include but which proves at all valuable to you, simply file a bug
and we can likely put it under -Wextra. Whether you explicitly enable some
subset of the warnings in -Wextra will depend heavily on your code, your
coding style, and whether maintaining that list is easier than fixing
everything uncovered by -Wextra.

Of the OP's list of warnings (which included both -Wall and -Wextra) only
the following warnings are not covered by those two groups (or turned on by
default). The first group emphasize why over-reliance on explicit warning flags
can be bad: none of these are even implemented in Clang! They're accepted on
the command line only for GCC compatibility.

-Wbad-function-cast

-Wdeclaration-after-statement

-Wmissing-format-attribute

-Wmissing-noreturn

-Wnested-externs

-Wnewline-eof

-Wold-style-definition

-Wredundant-decls

-Wsequence-point

-Wstrict-prototypes

-Wswitch-default

The next bucket of unnecessary warnings in the original list are ones which are
redundant with others in that list:

-Wformat-nonliteral -- Subset of -Wformat=2

-Wshorten-64-to-32 -- Subset of -Wconversion

-Wsign-conversion -- Subset of -Wconversion

There are also a selection of warnings which are more categorically different.
These deal with language dialect variants rather than with buggy or non-buggy
code. With the exception of -Wwrite-strings, these all are warnings for
language extensions provided by Clang. Whether Clang warns about their use
depends on the prevalence of the extension. Clang aims for GCC compatibility,
and so in many cases it eases that with implicit language extensions that are
in wide use. -Wwrite-strings, as commented on the OP, is a compatibility flag
from GCC that actually changes the program semantics. I deeply regret this
flag, but we have to support it due to the legacy it has now.

-Wfour-char-constants

-Wpointer-arith

-Wwrite-strings

The remaining options which are actually enabling potentially interesting
warnings are these:

-Wcast-align

-Wconversion

-Wfloat-equal

-Wformat=2

-Wimplicit-atomic-properties

-Wmissing-declarations

-Wmissing-prototypes

-Woverlength-strings

-Wshadow

-Wstrict-selector-match

-Wundeclared-selector

-Wunreachable-code

The reason that these aren't in -Wall or -Wextra isn't always clear. For
many of these, they are actually based on GCC warnings (-Wconversion,
-Wshadow, etc.) and as such Clang tries to mimic GCC's behavior. We're
slowly breaking some of these down into more fine-grain and useful warnings.
Those then have a higher probability of making it into one of the top-level
warning groups. That said, to pick on one warning, -Wconversion is so broad
that it will likely remain its own "top level" category for the foreseeable
future. Some other warnings which GCC has but which have low value and high
false-positive rates may be relegated to a similar no-man's-land.

Other reasons why these aren't in one of the larger buckets include simple
bugs, very significant false-positive problems, and in-development warnings.
I'm going to look into filing bugs for the ones I can identify. They should all
eventually migrate into a proper large bucket flag or be removed from Clang.

I hope this clarifies the warning situation with Clang and provides some
insight for those trying to pick a set of warnings for their use, or their
company's use.

OwnerDisplayName: Macmade

Body:
For context, I'm a Clang developer working at Google. At Google, we've rolled
Clang's diagnostics out to (essentially) all of our C++ developers, and we
treat Clang's warnings as errors as well. As both a Clang developer and one of the larger users of Clang's diagnostics I'll try to shed some light on these flags and how they can be used. Note that everything I'm describing is generically applicable to Clang, and not specific to C, C++, or Objective-C.

TL;DR Version: Please use -Wall and -Werror at a minimum on any new code
you are developing. We (the compiler developers) add warnings here for good
reasons: they find bugs. If you find a warning that catches bugs for you, turn
it on as well. Try -Wextra for a bunch of good candidates here. If one of
them is too noisy for you to use profitably, file a bug. If you write code that
contains an "obvious" bug but the compiler didn't warn about it, file a bug.

Now for the long version. First some background on warning flag groupings.
There are a lot of "groupings" of warnings in Clang (and to a limited extent in
GCC). Some that are relevant to this discussion:

On-by-default: These warnings are always on unless you explicitly disable them.

-Wall: These are warnings that the developers have high confidence in
both their value and a low false-positive rate.

-Wextra: These are warnings that are believed to be valuable and sound
(i.e., they aren't buggy), but they may have high false-positive rates or
common philosophical objections.

-Weverything: This is an insane group that literally enables every
warning in Clang. Don't use this on your code. It is intended strictly for
Clang developers or for exploring what warnings exist.

There are two primary criteria mentioned above which guide where warnings go in
Clang, and let's clarify what these really mean. The first is the potential
value of a particular occurrence of the warning. This is the expected
benefit to the user (developer) when the warning fires and correctly
identifies an issue with the code.

The second criteria is the idea of false-positive reports. These are
situations where the warning fires on code, but the potential problem being
cited does not in fact occur due to the context or some other constraint of the
program. The code warned about is actually behaving correctly. These are
especially bad when the warning was never intended to fire on that code
pattern. Instead, it is a deficiency in the warning's implementation that causes
it to fire there.

For Clang warnings, the value is required to be in terms of correctness,
not in terms of style, taste, or coding conventions. This limits the set of
warnings available, precluding oft-requested warnings such as warning
whenever {}s are not used around the body of an if statement. Clang is also
very intolerant of false-positives. Unlike most other compilers it will use
an incredible variety of information sources to prune false positives including
the exact spelling of the construct, presence or absence of extra '()', casts,
or even preprocessor macros!

Now let's take some real-world example warnings from Clang, and look at how
they are categorized. First, a default-on warning:

% nl x.cc
     1  class C { const int x; };

% clang -fsyntax-only x.cc
x.cc:1:7: warning: class 'C' does not declare any constructor to initialize its non-modifiable members
class C { const int x; };
      ^
x.cc:1:21: note: const member 'x' will never be initialized
class C { const int x; };
                    ^
1 warning generated.

Here no flag was required to get this warning. The rationale is that this is
code is never really correct, giving the warning high value, and the
warning only fires on code that Clang can prove falls into this bucket, giving
it a zero false-positive rate.

% nl x2.cc
     1  int f(int x_) {
     2    int x = x;
     3    return x;
     4  }

% clang -fsyntax-only -Wall x2.cc
x2.cc:2:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
  int x = x;
      ~   ^
1 warning generated.

Clang requires the -Wall flag for this warning. The reason is that there is
a non-trivial amount of code out there which has used (for good or ill) the
code pattern we are warning about to intentionally produce an uninitialized
value. Philosophically, I see no point in this, but many others disagree and
the reality of this difference in opinion is what drives the warning under the
-Wall flag. It still has very high value and a very low
false-positive rate, but on some codebases it is a non-starter.

% nl x3.cc
     1  void g(int x);
     2  void f(int arr[], unsigned int size) {
     3    for (int i = 0; i < size; ++i)
     4      g(arr[i]);
     5  }

% clang -fsyntax-only -Wextra x3.cc
x3.cc:3:21: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
  for (int i = 0; i < size; ++i)
                  ~ ^ ~~~~
1 warning generated.

This warning requires the -Wextra flag. The reason is that there are very
large codebases where mis-matched sign on comparisons is extremely common.
While this warning does find some bugs, the probability of the code being a bug
when the user writes it is fairly low on average. The result is an extremely
high false-positive rate. However, when there is a bug in a program due to
the strange promotion rules, it is often extremely subtle making this warning
when it flags a bug have relatively high value. As a consequence, Clang
provides it and exposes it under a flag.

Typically, warnings don't live long outside of the -Wextra flag. Clang tries
very hard to not implement warnings which do not see regular use and testing.
The additional warnings turned on by -Weverything are usually warnings under
active development or with active bugs. Either they will be fixed and placed
under appropriate flags, or they should be removed.

Now that we have an understanding of how these things work with Clang, let's
try to get back to the original question: what warnings should you turn on for
your development? The answer is, unfortunately, that it depends. Consider the
following questions to help determine what warnings work best for your
situation.

Do you have control over all of your code, or is some of it external?

What are your goals? Catching bugs, or writing better code?

What is your false-positive tolerance? Are you willing to write extra code
to silence warnings on a regular basis?

First and foremost, if you don't control the code, don't try turning extra
warnings on there. Be prepared to turn some off. There is a lot of bad code in
the world, and you may not be able to fix all of it. That is OK. Work to find a
way to focus your efforts on the code you control.

Next, figure out what you want out of your warnings. This is different for
different people. Clang will try to warn without any options on egregious bugs,
or code patterns for which we have long historical precedent indicating the bug
rate is extremely high. By enabling -Wall you're going to get a much more
aggressive set of warnings targeted at catching the most common mistakes that
Clang developers have observed in C++ code. But with both of these the
false-positive rate should remain quite low.

Finally, if you're perfectly willing to silence false-positives at every
turn, go for -Wextra. File bugs if you notice warnings which are catching
a lot of real bugs, but which have silly or pointless false positives. We're
constantly working to find ways to bring more and more of the bug-finding logic
present in -Wextra into -Wall where we can avoid the false-positives.

Many will find that none of these options is just-right for them. At Google,
we've turned some warnings in -Wall off due to a lot of existing code that
violated the warning. We've also turned some warnings on explicitly, even
though they aren't enabled by -Wall, because they have a particularly high
value to us. Your mileage will vary, but will likely vary in similar ways. It
can often be much better to enable a few key warnings rather than all of
-Wextra.

I would encourage everyone to turn on -Wall for any non-legacy code. For
new code, the warnings here are almost always valuable, and really make the
experience of developing code better. Conversely, I would encourage everyone to
not enable flags beyond -Wextra. If you find a Clang warning that -Wextra
doesn't include but which proves at all valuable to you, simply file a bug
and we can likely put it under -Wextra. Whether you explicitly enable some
subset of the warnings in -Wextra will depend heavily on your code, your
coding style, and whether maintaining that list is easier than fixing
everything uncovered by -Wextra.

Of the OP's list of warnings (which included both -Wall and -Wextra) only
the following warnings are not covered by those two groups (or turned on by
default). The first group emphasize why over-reliance on explicit warning flags
can be bad: none of these are even implemented in Clang! They're accepted on
the command line only for GCC compatibility.

-Wbad-function-cast

-Wdeclaration-after-statement

-Wmissing-format-attribute

-Wmissing-noreturn

-Wnested-externs

-Wnewline-eof

-Wold-style-definition

-Wredundant-decls

-Wsequence-point

-Wstrict-prototypes

-Wswitch-default

The next bucket of unnecessary warnings in the original list are ones which are
redundant with others in that list:

-Wformat-nonliteral -- Subset of -Wformat=2

-Wshorten-64-to-32 -- Subset of -Wconversion

-Wsign-conversion -- Subset of -Wconversion

There are also a selection of warnings which are more categorically different.
These deal with language dialect variants rather than with buggy or non-buggy
code. With the exception of -Wwrite-strings, these all are warnings for
language extensions provided by Clang. Whether Clang warns about their use
depends on the prevalence of the extension. Clang aims for GCC compatibility,
and so in many cases it eases that with implicit language extensions that are
in wide use. -Wwrite-strings, as commented on the OP, is a compatibility flag
from GCC that actually changes the program semantics. I deeply regret this
flag, but we have to support it due to the legacy it has now.

-Wfour-char-constants

-Wpointer-arith

-Wwrite-strings

The remaining options which are actually enabling potentially interesting
warnings are these:

-Wcast-align

-Wconversion

-Wfloat-equal

-Wformat=2

-Wimplicit-atomic-properties

-Wmissing-declarations

-Wmissing-prototypes

-Woverlength-strings

-Wshadow

-Wstrict-selector-match

-Wundeclared-selector

-Wunreachable-code

The reason that these aren't in -Wall or -Wextra isn't always clear. For
many of these, they are actually based on GCC warnings (-Wconversion,
-Wshadow, etc.) and as such Clang tries to mimic GCC's behavior. We're
slowly breaking some of these down into more fine-grain and useful warnings.
Those then have a higher probability of making it into one of the top-level
warning groups. That said, to pick on one warning, -Wconversion is so broad
that it will likely remain its own "top level" category for the foreseeable
future. Some other warnings which GCC has but which have low value and high
false-positive rates may be relegated to a similar no-man's-land.

Other reasons why these aren't in one of the larger buckets include simple
bugs, very significant false-positive problems, and in-development warnings.
I'm going to look into filing bugs for the ones I can identify. They should all
eventually migrate into a proper large bucket flag or be removed from Clang.

I hope this clarifies the warning situation with Clang and provides some
insight for those trying to pick a set of warnings for their use, or their
company's use.


问:
What kind of interface should a double container offer?
I want to write a class which offers two sequences of elements to its users. The first one (lets call it "primary") is the main of the class and will be use 80% of the time. The second one (lets call it "secondary") is less important, but still need to be in the same class. The question is: what interface should the class offer to its users?

By looking at STL style, a class with a single sequence of elements should offer begin() and end() functions for traversal and function like insert() and erase() for modifications.

But how should my class offer the second sequence?

For now, I have two ideas:

Expose the two containers to the user (what about the Law of Demeter ?)

Provide the main container with STL interface and expose only the second one.

Here is an example.

```<code>#include <vector>

class A {
    public:
        std::vector<int>&  primary();
        std::vector<char>& secondary();

    private:
        std::vector<int>  m_primary;
        std::vector<char> m_secondary;
};

class B {
    public:
        std::vector<int>::iterator begin();
        std::vector<int>::iterator end();
        std::vector<char>& secondary();

    private:
        std::vector<int>  m_primary;
        std::vector<char> m_secondary;
};

// Classes implementation
// ...

int main() {

    // --------------------------------------------------
    // Case 1
    // --------------------------------------------------

    A a;

    for(auto it = a.primary().begin(); it != a.primary().end(); ++it) {
        // ...
    }
    for(auto it = a.secondary().begin(); it != a.secondary().end(); ++it) {
        // ...
    }

    // --------------------------------------------------
    // Case 2
    // --------------------------------------------------

    B b;

    for(auto it = b.begin(); it != b.end(); ++it) {
        // ...
    }
    for(auto it = b.secondary().begin(); it != b.secondary().end(); ++it) {
        // ...
    }
}
</code>```

What is the more C++ish way to do that? Is one best than the other or is there an other solution?

Context

This problem came in the context of an exercise in which I am writing a simple database access framework. Here are the classes involved in the question:

table

column

row

field

The table class consists of a sequence of columns and an other sequence of rows. The main use of the table is manipulating (access, add and remove) the rows.

Deeper in the hierarchy, a row is made of column and field so a user can ask the value (field) corresponding to a given column or column name. Each time a column is add/modify/remove from the table, every rows will need to be modify to reflect the modification.

I want the interface to be simple, extensible and combining well with existing code (like STL or Boost).

答:
Note that many STL containers have a second interface to iterate in the reverse direction: rbegin and rend!

So there is prior art to use begin() and end() for the primary interface, and e.g. sec_begin() and sec_end() for the secondary interface.

Something like (typedefs added for increased readability):

```<code>class B {
    public:
        typedef std::vector<int>::iterator iterator;
        typedef std::vector<char>::iterator secondary_iterator;

        iterator begin() { return m_primary.begin(); }
        iterator end()   { return m_primary.end(); }

        secondary_iterator sec_begin() { return m_secondary.begin(); }
        secondary_iterator sec_end()   { return m_secondary.end(); }

    private:
        std::vector<int>  m_primary;
        std::vector<char> m_secondary;
};
</code>```

Additional remark: Note that non-const iterators are being returned. If you really want both containers to act synchronized (that is: changing one should change the other), it might be better to return the const_iterator versions. begin()/end()/... can become const member functions.

The typedefs I added will help switching if you decide to do so.

ContentLicense: CC BY-SA 3.0

Body:
Note that many STL containers have a second interface to iterate in the reverse direction: rbegin and rend!

So there is prior art to use begin() and end() for the primary interface, and e.g. sec_begin() and sec_end() for the secondary interface.

Something like (typedefs added for increased readability):

class B {
    public:
        typedef std::vector<int>::iterator iterator;
        typedef std::vector<char>::iterator secondary_iterator;

        iterator begin() { return m_primary.begin(); }
        iterator end()   { return m_primary.end(); }

        secondary_iterator sec_begin() { return m_secondary.begin(); }
        secondary_iterator sec_end()   { return m_secondary.end(); }

    private:
        std::vector<int>  m_primary;
        std::vector<char> m_secondary;
};

Additional remark: Note that non-const iterators are being returned. If you really want both containers to act synchronized (that is: changing one should change the other), it might be better to return the const_iterator versions. begin()/end()/... can become const member functions.

The typedefs I added will help switching if you decide to do so.


问:
In the aggregate: how will we maintain legacy systems?

NEW YORK - With a blast that made
  skyscrapers tremble, an 83-year-old
  steam pipe sent a powerful message
  that the miles of tubes, wires and
  iron beneath New York and other U.S.
  cities are getting older and could
  become dangerously unstable.

July 2007 Story About a Burst Steam Pipe in Manhattan

We've heard about software rot and technical debt.

And we've heard from the likes of:

"Uncle Bob" Martin - Who warned us about "the consequences of making a mess".

Michael C. Feathers - Who gave us guidance for 'Working Effectively With Legacy Code'.

So certainly the software engineering community is aware of these issues.

But I feel like our aggregate society does not appreciate how these issues can plague working systems and applications.

As Steve McConnell notes:

...Unlike financial debt, technical
  debt is much less visible, and so
  people have an easier time ignoring
  it.

If this is true, and I believe that it is, then I fear that governments and businesses may defer regular maintenance and fortification against hackers until it is too late. [Much like NYC and the steam pipes.]

My Question:

Is there a way that we can avoid the
software equivalent of NYC and the steam pipes?

答:
Having supported a variety of government and private industry applications I would say that most companies and at least the US Government is well aware of the dangers of letting code rot and not staying on top of the latest security trends.

We regularly have to get our software certified for various susceptibilities and most government electronic systems, even old ones, get regular updates to keep them secure.

Of course there are exceptions, and hackers are always on the move, but on the whole I think people are pretty aware you can't just throw something out there and never touch it again.

ContentLicense: CC BY-SA 2.5


问:
What are the causes that lead to an overbloated software?
Today I decided to perform a clean install for Creative Sound Blaster drivers, as they always start glitching all by themselves after some time. And that meant I had to go through the whole cleanup procedure. And that took me almost 2 hours..

And honestly, I can't see a reason why?! And although Creative, IMHO, is an absolute 1st place winner for producing poor quality software that never works, the bloat problem is not exclusive to them.

PC with Canon digital camera driver will have around 10 Canon entries that are interconnected with all sorts of connections. Visual Studio is also a prime example, there is around 50 or so entries for full install, and repairing that thing is only possible with complete nuking. And once it even managed to ruin the whole OS install when I was upgrading from VS2k8 to VS2k8SP1 or something. As it turns out 5GB of free space was not enough for 300Mb patch...

So this really seem to be a widespread problem. Almost every application nowadays usually contains unpackers, multiple spywarish "friends" that are installed, drivers are usually around 600Mb for everything including printers and so on.

But why? Is it developer fault? Applications like that are nightmare to support, they never work 100% nowadays, and almost all users I know are very negative about all that bloat they get as a mandatory driver install for USB thumb drive/Printer/Camera/Sound Card/Browser.

It seems that NSIS from Nullsoft is the only clean setup system that is not bloated, from what I know, for example, Firefox install. Clean, pretty much xcopy based install without any problems.

So why people are not using simple setups and applications that are not rooted over 30 layers of interconnection? Is it because developers are lazy? Use of codegen tools? Is it because corporations force heavyweight apps as something users will love? What's the cause, and is there a hope software will return back to basics someday? What are the steps to avoid writing bloat when you start new application from scratch?

答:
"We need something to do X. Let's use library $BIGFATLIBDESIGNEDFORSOMETHINGELSE, because I used it in a different project"

"I think we don't need this code part anymore, but to make sure that nothing breaks, just keep it"

No or not enough unit tests, which lead to

No refactoring

No tracking, where settings have been stored over the years, so now the settings are everywhere

...


问:
What is a practical way to debug Rails?
I get the impression that in practice, debuggers are rarely used for Rails applications. (Likewise for other Ruby apps, as well as Python.)

We can compare this to the usual practice for  Java or VisualStudio programmers--they use an interactive debugger in a graphical IDE.

How do people debug Rails applications in practice? I am aware of the variety of debuggers, so no need to mention those, but do serious Rails programmers work without them? If so, why do you choose to do it this way?

It seems to me that console printing has its limits when debugging complex logic.

答: I think your question is a little poor in its presumption; I use an interactive debugger in a graphical IDE (both in Netbeans and RubyMine depending on where I'm working) to debug Rails development.</p>

Title: What is a practical way to debug Rails?


问:
What do you think of this Exception handling practice
I'm working on a project that includes a lot of creating/manipulating and reading JSONObjects and arrays but not in a systematic way. So there is JSON code everywhere.

It is ok for me except that every time I work on a JSONObject I got to handle JSONException.

So I created a class that extends JSONObject and Override the put/get methods in it and handled JSONExceptions inside this class.

It made my code way much clearer and I believe it is more than enough for my case.

What do you think?

答:
I created a class that extends JSONObject and Override the put/get methods in it and handled JSONExceptions inside this class.

This may be perfectly fine or perfectly sucky depending on how you handled the exception inside that class. When (when, not if) an exception arises, what happens? Perhaps there is some central error handler that you're using? How do the users of your JSONObject subclass know if something went awry?

Or do you have a guarantee that things simply can't go awry? If yes, then you should still have some sort of assertion mechanism to catch the impossible.

Exceptions and errors can be handled in myriad of ways. Most of the ways are all right as long as things crash early, with as specific error message as possible, and won't just fail silently later on.


问:
Why pointer symbol and multiplication sign are same in C/C++?
I am writing a limited C/C++ code parser. Now, multiplication and pointer signs give me really a tough time, as both are same. For example,

```<code>int main ()
{
  int foo(X * p); // forward declaration
  bar(x * y);  // function call
}
</code>```

I need to apply special rules to sort out if * is indeed a pointer. In above code, I have to find out if foo() is a forward declaration and bar() is a function call. Real world code can be lot more complex. Had there been different symbol like @ for pointers, then it would have been straight forward.

The pointers were introduced in C, then why some different symbol was not chosen for the same ? Was keyboard so limited ?

[It will be an add-on if someone can throw light on how modern day parser deal with this ? Keep in mind that, in one scope X can be typename and another scope it can be a variable name, at the same time.]

答:
They're resolved by using symbol tables. This symbol table keeps track of the declarations you've seen to sort out whether or not you're calling a function that's already been declared. When the parser encounters an identifier, it makes a lookup to the symbol table to see what it is. You will find similar situations for type names- especially since C has multiple namespaces and you can start shadowing them. These rules are non-trivial.

```<code>typedef int MahInt;
MahInt * p; // declaration or multiplication?
</code>```

It is not possible to parse C without symbol tables.

As for why it is that way, because keyboards at the time were very limited- for example digraphs and trigraphs, which produce symbols that were unusual at the time.  For example, witness the "WTF" operator:

```<code>int x, y;
x ??!??! y;
</code>```

which is really

```<code>x || y
</code>```

Body:
They're resolved by using symbol tables. This symbol table keeps track of the declarations you've seen to sort out whether or not you're calling a function that's already been declared. When the parser encounters an identifier, it makes a lookup to the symbol table to see what it is. You will find similar situations for type names- especially since C has multiple namespaces and you can start shadowing them. These rules are non-trivial.

typedef int MahInt;
MahInt * p; // declaration or multiplication?

It is not possible to parse C without symbol tables.

As for why it is that way, because keyboards at the time were very limited- for example digraphs and trigraphs, which produce symbols that were unusual at the time.  For example, witness the "WTF" operator:

int x, y;
x ??!??! y;

which is really

x || y


答: From what I understand, you prefer not handling checked exceptions. The simplest solution might be that your extended class simply wraps checked JSON exception into new Runtime Exception.</p>

Title: What do you think of this Exception handling practice

Body:
I'm working on a project that includes a lot of creating/manipulating and reading JSONObjects and arrays but not in a systematic way. So there is JSON code everywhere.

It is ok for me except that every time I work on a JSONObject I got to handle JSONException.

So I created a class that extends JSONObject and Override the put/get methods in it and handled JSONExceptions inside this class.

It made my code way much clearer and I believe it is more than enough for my case.

What do you think?


问:
Design Methodology for Developing Interoperable Systems?
A bit of background

The company I work for has been creating database applications since around 1980 and, until relatively recently, most of these systems have been stand-alone "silo" systems.

However, in the last few years, we've seen more of a shift towards gathering "intelligence" across all systems within our customers requirements.  For example, a system that might collect data about people's dental records may need to talk to a system that collects data about people's optician records, share information about the same person and provide search capabilities across both systems (makes sense, although the example I've used is fictional).

In the fictional example above, the dental and optician systems may or may not both be written by the company I work for (in other words we are looking at both internally-developed interfaces and interfaces to systems from third-party providers).

What we've done so far

We have a basic web-services API (.asmx) for one of our products, but I'm concerned about the change management, in terms of keeping it up-to-date as we add new features to the main product (in terms of providing the new features through the API without breaking compatibility with older interfaces).

We have also produced one WCF service.  The rigid contracts put my mind slightly more at ease than working with the ASMX service, but I think a lack of experience within the company is holding us back, so I'm looking for some guidance on best practice that I can read up on to help move us along (or at least point us in the right direction).

The question

Is there a particular methodology or programming practice for designing systems to maximise their ability to interface to other systems?

Are there any good online (or offline) resources for these programming practices (assuming they exist)?

Any other advice you can provide based on the information above would be appreciated, but not essential.

We primarily develop in Microsoft .NET (mainly ASP.NET, with some windows forms applications as well) with a SQL Server/Oracle database back-end, although I expect the programming practices might be language independent.  (I've used the .NET tag as an afterthought, but I might take it out later..!)

Thanks for your time.

答:
My experience with this is very small, but I believe you could look into SOA (service oriented architecture). Its goal is exactly what you want: interoperable software components.

Don't confuse SOA services with the typical .NET services (asmx, wcf). The communication between 2 SOA services can go through asmx or wcf, but can also use Messaging (MSMQ, ...) for example.


问:
What's the term for "while(true)" loop with "break" inside?
Suppose I have a loop in C++ or C# that goes like this:

```<code>while( true ) {
    doSomething();
    if( condition() ) {
        break;
    }
    doSomethingElse();
}
</code>```

This is commonly called "infinite loop". Yet it is not technically infinite - it will stop once control flows through break.

What's the term for such loop - that has "loop forever" loop control statement and "break" inside?

答:
I have to agree with sbi here - I like the middle-checking loop term. This kind of construct was more popular when Structured Programming started to roll and many languages had syntactic support for them.

That said, it is now widespread knowledge that while loops are usually more mantainable, since it is easier to reason about invariants and they often handle the tricky empty case better.

In your particular case your loop is just equivalent to

```<code>for(; doSomething(), !condition(); doSomethingElse()){}
</code>```

so I would only use the break version if either doSomething or doSomethingElse involved multiple statements and I'd rather not put them away into separate functions like you did.

That said, if your loop is more complicated then a (start, check, increment) iteration then you should consider refactoring it into something simpler.

Body:
I have to agree with sbi here - I like the middle-checking loop term. This kind of construct was more popular when Structured Programming started to roll and many languages had syntactic support for them.

That said, it is now widespread knowledge that while loops are usually more mantainable, since it is easier to reason about invariants and they often handle the tricky empty case better.

In your particular case your loop is just equivalent to

for(; doSomething(), !condition(); doSomethingElse()){}

so I would only use the break version if either doSomething or doSomethingElse involved multiple statements and I'd rather not put them away into separate functions like you did.

That said, if your loop is more complicated then a (start, check, increment) iteration then you should consider refactoring it into something simpler.


答:
It is not so bad in every case. I find myself writing this kind of loops with certain kind of APIs. Say, for instance, that you have a loop object, and need to check for some condition quite deep in it, like so:

```<code>while (loop
    .getAExecutionModelFactory()
    .getActiveXexecutor()
    .getYCancelModelHandler()
    .getCurrentHandler()
    .isCancelled()) {
        // ... do something with the current Handler ....
        loop = ..... // prepare for next loop
}
</code>```

Now suppose every getXXX-method could potentially return null. Then it would be still possible to write a boolean expression, although a quite complicated and unreadable one. And then we have to do redo almost the same to get at the current handler object.
In such cases, I find it easier to write a while (true) loop with break and continue.

Title: What's the term for "while(true)" loop with "break" inside?

Body:
Suppose I have a loop in C++ or C# that goes like this:

```<code>while( true ) {
    doSomething();
    if( condition() ) {
        break;
    }
    doSomethingElse();
}
</code>```

This is commonly called "infinite loop". Yet it is not technically infinite - it will stop once control flows through break.

What's the term for such loop - that has "loop forever" loop control statement and "break" inside?

Body:
It is not so bad in every case. I find myself writing this kind of loops with certain kind of APIs. Say, for instance, that you have a loop object, and need to check for some condition quite deep in it, like so:

while (loop
    .getAExecutionModelFactory()
    .getActiveXexecutor()
    .getYCancelModelHandler()
    .getCurrentHandler()
    .isCancelled()) {
        // ... do something with the current Handler ....
        loop = ..... // prepare for next loop
}

Now suppose every getXXX-method could potentially return null. Then it would be still possible to write a boolean expression, although a quite complicated and unreadable one. And then we have to do redo almost the same to get at the current handler object.
In such cases, I find it easier to write a while (true) loop with break and continue.


问:
How can I inspire engineers to positively conduct telephone interviews
Our (mid-size) company (with 150 employees) has witnessed considerable growth since last year, and as a result we have been conducting lots of interviews to hire more and more engineers to bring new projects in motion.

To begin with, following is our interview process

Screening resume by HR

Telephone technical interview (conducted by senior engg)

Final technical + HR interview (conducted by team-lead/PM)

After some analysis we found that telephone interviews are not really becoming effective, due to which we are not able to find good number of engineers in final interview. My analysis revealed that engineers don't consider interviewing as important/serious activity, since it's internal and non-billable. Also I see that engineers don't find it really prestigious to carry a label of "interviewer" (at-least telephone interviewer). We do have  set of good experienced engineers in company who can take any interview very effectively, but since number of telephonic interviews is large, this pool is not sufficient. Hence we try to use other engineers as well.

What can be done to inspire engineers to conduct telephone interviews seriously and positively (not treating this as mundane job)?

[Update-2011/12/28]

Thanks for sharing your valuable opinions. It really helped me to look at problem from variety of different angles. Alongside I was discussing issues with few colleagues as well and I personally feel that there is no single silver bullet for such issue. I will need to think recruitment process as a whole unit and plan to improve different areas/stages in it.

答:
Make sure to communicate appreciation when people do a good job on interviews. There are a variety of ways to do this, already explained at length in various articles about management, but the important thing is that people want to be appreciated so make this a way to be appreciated.

So if you have some good candidates in the final interview then thank the telephone interviewers for passing along good candidates, and note it down to bring up as showing leadership skills in their next evaluation.

OwnerDisplayName: FutureProof


答:
I would suggest using something free like Protocol Buffers. It's available for all major languages, comes with generators and is reasonably fast. And it is proven in the field.

From the looks of it, the strength of WCF lies in its ability to consume a huge variety of formats. However in a long term perspective, your interest should be to shape your providers for interoperability, not your consumers.

Title: Design Methodology for Developing Interoperable Systems?

Body:
A bit of background

The company I work for has been creating database applications since around 1980 and, until relatively recently, most of these systems have been stand-alone "silo" systems.

However, in the last few years, we've seen more of a shift towards gathering "intelligence" across all systems within our customers requirements.  For example, a system that might collect data about people's dental records may need to talk to a system that collects data about people's optician records, share information about the same person and provide search capabilities across both systems (makes sense, although the example I've used is fictional).

In the fictional example above, the dental and optician systems may or may not both be written by the company I work for (in other words we are looking at both internally-developed interfaces and interfaces to systems from third-party providers).

What we've done so far

We have a basic web-services API (.asmx) for one of our products, but I'm concerned about the change management, in terms of keeping it up-to-date as we add new features to the main product (in terms of providing the new features through the API without breaking compatibility with older interfaces).

We have also produced one WCF service.  The rigid contracts put my mind slightly more at ease than working with the ASMX service, but I think a lack of experience within the company is holding us back, so I'm looking for some guidance on best practice that I can read up on to help move us along (or at least point us in the right direction).

The question

Is there a particular methodology or programming practice for designing systems to maximise their ability to interface to other systems?

Are there any good online (or offline) resources for these programming practices (assuming they exist)?

Any other advice you can provide based on the information above would be appreciated, but not essential.

We primarily develop in Microsoft .NET (mainly ASP.NET, with some windows forms applications as well) with a SQL Server/Oracle database back-end, although I expect the programming practices might be language independent.  (I've used the .NET tag as an afterthought, but I might take it out later..!)

Thanks for your time.


答:
There are two rules in the C BNF that make writing a parser difficult:

```<code>if-statement: "if" expression statement |
              "if" expression statement "else" statement
</code>```

leads to the dangling else problem, where

```<code>if a if b c else d
</code>```

can be parsed as either of

```<code>(if-statement (a) (if-statement (b) (c) (d)))
(if-statement (a) (if-statement (b) (c)) (d))
</code>```

The typical resolution for this conflict is to prefer shift over reduce, attaching the "else" branch to the inner if-statement.

The other, more difficult problem is

```<code>typedef-name: identifier
</code>```

which makes the language context sensitive. This conflict is resolved by omitting the rule in the parser and creating a separate token for typedef-names; for this to work, the scanner must have a table of names that have been declared as typedef.

For C++, the rules are a lot more complex, and it is usually simpler to write an integrated scanner/parser that resolves all identifiers.

Title: Why pointer symbol and multiplication sign are same in C/C++?

Body:
I am writing a limited C/C++ code parser. Now, multiplication and pointer signs give me really a tough time, as both are same. For example,

```<code>int main ()
{
  int foo(X * p); // forward declaration
  bar(x * y);  // function call
}
</code>```

I need to apply special rules to sort out if * is indeed a pointer. In above code, I have to find out if foo() is a forward declaration and bar() is a function call. Real world code can be lot more complex. Had there been different symbol like @ for pointers, then it would have been straight forward.

The pointers were introduced in C, then why some different symbol was not chosen for the same ? Was keyboard so limited ?

[It will be an add-on if someone can throw light on how modern day parser deal with this ? Keep in mind that, in one scope X can be typename and another scope it can be a variable name, at the same time.]

Body:
There are two rules in the C BNF that make writing a parser difficult:

if-statement: "if" expression statement |
              "if" expression statement "else" statement

leads to the dangling else problem, where

if a if b c else d

can be parsed as either of

(if-statement (a) (if-statement (b) (c) (d)))
(if-statement (a) (if-statement (b) (c)) (d))

The typical resolution for this conflict is to prefer shift over reduce, attaching the "else" branch to the inner if-statement.

The other, more difficult problem is

typedef-name: identifier

which makes the language context sensitive. This conflict is resolved by omitting the rule in the parser and creating a separate token for typedef-names; for this to work, the scanner must have a table of names that have been declared as typedef.

For C++, the rules are a lot more complex, and it is usually simpler to write an integrated scanner/parser that resolves all identifiers.


答: On Rosetta Code, this particular pattern is described as an “N plus one half” loop. While it's not my favorite term, it's not terrible and is clearly a pattern that is useful for some kinds of loops. (The alternatives are to duplicate the before-the-condition code — potentially tricky in real programs — or to increase the nesting depth of the after-the-condition code while adding a loop condition variable; neither improves the maintainability or understandability of the code. The only reason for rejecting such constructs is if one insists on writing loops to be break-free.)


答:
The single best way to inspire your engineers to not only be okay with interviewing but get them to actively wish for interviews is to communicate to them how it is in their best interest to interview others.

We have all worked on projects with an idiot who somehow made it through the screening process.  It sucks.  The person is less than useless and actually creates more work for the entire team.  In the end because the person in not dependable, everybody pulls more weight to try and take the work away from that person.

After being through this experience so many times, I not only wanted to do interviews, I would fight for the chance to do them because I wanted to make sure that unqualified candidates didn't make it through the screening process.

If you communicate to the engineers that if they interview, they are helping to make sure that unqualified engineers do not make it onto their project teams and give them grief.

This of course only works in a company that works towards building long term working relationships with their engineer employees.  The engineers must feel vested in the company in the beginning or they will simply not care.  If all of your engineers are just biding their time to the next contract or the next big offer then nothing you do will get them enthusiastic about interviewing.

This may not be your company, but could also just be an aspect of the culture in your country.

Title: How can I inspire engineers to positively conduct telephone interviews

Body:
Our (mid-size) company (with 150 employees) has witnessed considerable growth since last year, and as a result we have been conducting lots of interviews to hire more and more engineers to bring new projects in motion.

To begin with, following is our interview process

Screening resume by HR

Telephone technical interview (conducted by senior engg)

Final technical + HR interview (conducted by team-lead/PM)

After some analysis we found that telephone interviews are not really becoming effective, due to which we are not able to find good number of engineers in final interview. My analysis revealed that engineers don't consider interviewing as important/serious activity, since it's internal and non-billable. Also I see that engineers don't find it really prestigious to carry a label of "interviewer" (at-least telephone interviewer). We do have  set of good experienced engineers in company who can take any interview very effectively, but since number of telephonic interviews is large, this pool is not sufficient. Hence we try to use other engineers as well.

What can be done to inspire engineers to conduct telephone interviews seriously and positively (not treating this as mundane job)?

[Update-2011/12/28]

Thanks for sharing your valuable opinions. It really helped me to look at problem from variety of different angles. Alongside I was discussing issues with few colleagues as well and I personally feel that there is no single silver bullet for such issue. I will need to think recruitment process as a whole unit and plan to improve different areas/stages in it.


答: You mentioned that it takes engineers away from billable hours.  Therefore, make this time more valuable by adding incentives for conducting interviews.  There could be a base value for simply taking the time to conduct the interview.  This could be followed up with an additional bonus for bringing well qualified candidates in for the final interview.</p>


答:
While the number of telephonic interviews is large, how else is this seen in the company?  Is it just another thing to do or is it something recognized and valued highly?  I'd question how well is management and the engineers that can do the interviews well communicating to those developing skills to do telephonic interviews as that could well be a big deal.

It may be worthwhile to consider pairing up those good experienced engineers with others to try to pass on their knowledge and develop the skills in others.  I do get that this may not be a liked solution but the alternative is consider what support are you giving to those developing the skills to do this kind of interview well?


问:
Correct For Loop Design
What is the correct design for a for loop?

Felix currently uses

```<code>if len a > 0 do
  for var i in 0 upto len a - 1 do
    println a.[i];
  done
done
</code>```

which is inclusive of the upper bound. This is necessary to support the full range of values of a typical integer type. However the for loop shown does not support zero length arrays, hence the special test, nor will the subtraction of 1 work convincingly if the length of the array is equal to the number of integers.
(I say convincingly because it may be that 0  - 1 = maxval: this is true in C for unsigned int, but are you sure it is true for unsigned char without thinking carefully about integral promotions?)

The actual implementation of the for loop by my compiler does correctly handle 0 but this requires two tests to implement the loop:

```<code>continue:
  if not (i <= bound) goto break
  body
  if i == bound goto break
  ++i
  goto continue
break:
</code>```

Throw in the hand coded zero check in the array example and three tests are needed.

If the loop were exclusive it would handle zero properly, avoiding the special test, but there'd be no way to express the upper bound of an array with maximum size.

Note the C way of doing this:

```<code>for(i=0; predicate(i); increment(i))
</code>```

has the same problem. The predicate is tested after the increment, but the terminating increment is not universally valid!

There is a general argument that a simple exclusive loop is enough: promote the index to a large type to prevent overflow, and assume no one will ever loop to the maximum value of this type.. but I'm not entirely convinced: if you promoted to C's size_t and looped from the second largest value to the largest you'd get an infinite loop!

答:
In C it would be for (int i = 0 ; i < (len a) ; i++ ) { }.  This would not execute any iterations since 0 is not < 0 (i < (len a)).

If you are going to use an unsigned then yes, you need to surround with the condition check.

Does it have a for element in array {} type function?

If it's considered functional there is a way to do with with recursion.

Title: Correct For Loop Design


答:
1) Bubble the exception up to a recoverable place in your code.  Then deal with it.

2) How are you getting to the point where you are worried about getting invalid data?  I like to keep my data as clean as possible.  If you do get an exception at that point then you can treat it like an exception.

3) You really should care about your code.  Go read thedailywtf.com to see about people who are "ok" with their (messy) code.


问:
Single responsibility principle - am I overusing it?
For reference - http://en.wikipedia.org/wiki/Single_responsibility_principle

I have a test scenario where in one module of application is responsible for creating ledger entries. There are three basic tasks which could be carried out -

View existing ledger entries in table format.

Create new ledger entry using create button.

Click on a ledger entry in the table (mentioned in first pointer) and view its details in next page. You could nullify a ledger entry in this page.

(There are couple more operation/validations in each page but fore sake of brevity I will limit it to these)

So I decided to create three different classes -

LedgerLandingPage

CreateNewLedgerEntryPage

ViewLedgerEntryPage

These classes offer the services which could be carried out in those pages and Selenium tests use these classes to bring application to a state where I could make certain assertion.

When I was having it reviewed with on of my colleague then he was over whelmed and asked me to make one single class for all. Though I yet feel my design is much clean I am doubtful if I am overusing Single Responsibility principle

答:
IMHO you shouldn't be using classes at all. There are no data abstractions here. The ledgers are a concrete data type. The methods for manipulating and displaying them are functions and procedures. There will certainly be many commonly used functions to be shared such as formatting a date.  There is little place for any data to be abstracted and hidden in a class in the display and selection routines.

There is some case to hide state in a class for ledger editing.

Whether or not you're abusing the SRP, you're abusing something more fundamental: you're overusing abstraction. It's a typical problem, engendered by the mythical notion OO is a sane development paradigm.

Programming is 90% concrete: use of data abstraction should be rare and carefully engineered. Functional abstraction, on the other hand should be more common, since language details and choice of algorithms need to be separated from the semantics of the operation.


答:
<Angry_rant_against_the_Billable_Hours_mind_set>

Truth be told, your company doesn’t deserve good developers.

I’ve worked for many consulting firms. When management continually stresses the importance of billable hours at every meeting and on every year end review. When the top guy at the firm gets up in front of the entire company and says “THE ONLY THING THAT MATTERS IS BILLABLE HOURS”. What do you expect from your developers? Bringing in good competition for billable hours will most likely reduce the consultant's (the one conducting the interview) billable hours. (By crowding the pool available hours)

Guess what else, and this is the part I hate most about this mind set: It rewards inefficacy and punishes efficacy. I have been told by a manager “Don’t you dare tell anyone you finished the project with only half the allotted hours, how can we bill for time not worked?”. (So yes, this is a time and material contract, where we basically stole from the client)

I say this will full confidence that the following is true: every single company that works with time and material contacts, are thieves. They will never give up more than a few hours of the allocated budget, yet will kick and scream, if they go over. (The only reason they give a few hours is so they can go back to the client proclaiming “Great News! We are under budget!”) It’s Thievery.

I say it again, your company doesn’t deserve good developers.

</Angry_rant_against_the_Billable_Hours_mind_set>

To answer the Question (per the comment below) : He simply needs to find someone who cares more about the well being of the firm, then his billable hours bonus to conduct the interview

Edit 12/17/11 - Saw this Dilbert and decided to added to add it here:


问:
Is it OK to pass the concrete client to a method on the concrete strategy?
When using the strategy pattern, is it good practice to pass this to a method on this.strategy?

I have a strategy interface with one call, TakeAction.  The idea is that TakeAction decides which of the several possible actions the Client should perform and then calls the appropriate method on the client.  So in a concrete strategy, the TakeAction method might look like:

```<code>void TakeAction(IAbstractClient client)
{
    if (client.IsBlah()) client.UnBlah(this.BlahValue1, this.BlahValue2);
    else if (client.CanFoo()) client.Foo(this.FooValue);
    else if (this.ShouldTwiddle()) client.Twiddle();
}
</code>```

And in the client, the call looks like:

```<code>this.strategy.TakeAction(this);
</code>```

Is this good form?  Or is there a better way to do this?  (Passing back a class with an enum describing the action and the values to pass to it seemed overkill.)

答:
Passing this to a strategy is perfectly fine. This lets you use polymorphism as intended.

So long as the class implements the IAbstractClient interface, you are good to go.


问:
Does any programming language use variables as they're in maths?
In maths, a variable means you can put any number there, and an equation will still be true:

```<code>root(square(x)) = abs(x)
</code>```

In programming languages, this is not so: a var can change. In Python:

```<code>y = (x**2)**.5
x *= 2
assert y == abs(x)
</code>```

will raise an exception, since x in the last line is not the same.

Are there programming languages that use immutable variables?

答:
You can simulate immutability in Python too by not allowing updates to classes.  As stated earlier most pure functional programming languages enforce immutability. Clojure is a recent addition to the JVM platform (Clojure is a LISP dialect)

In Scala (also a JVM language)  a unifier of OO and FP support variables declared with val are immutable. Scala expressiveness and OO/FP hybrid support makes it look similar to Mathematica. (Akka is a framework that adds Erlang OTP and Clojure functionality such as STM.. to Scala and Java.) LACASA adds type system and programming model to enforce the object capability discipline in Scala, and to provide unique object references. (code) (theoretical background)

In Java a variable declared final is immutable, and Java libraries such as Google Guava includes immutable libraries of collections. Java Strings are also always immutable.


答:
If there are any formations of teams on projects, those members should have an interest in getting qualified people to fill a vacant position.

You may want to start some sort of mentorship program where people who conduct these interviews have some responsibility for the person they recommended to actually become a productive employee. There should be consequences to recommending unqualified candidates as well as incentives when they recommend good ones.

A growing company needs to make this an activce responsibility and give people time to do this. You can't expect the same amount of billable hours for the people who have to conduct interviews as those who don't. Sounds like doing interviews is a form of working over-time and you wonder why no one wants to do it.

Edit:  This reminds me of pro bono work done by attorneys.


答:
The first thing I would look into is whether or not the interviewers KNOW HOW TO PERFORM INTERVIEWS and that the interviewers are following a coherent methodology.

A lot of orgs simply throw people into an interviewer seat without any effort to train the person for this task. It DOES takes some experience to learn interviewing. It is definitely a skill and you should not rely strictly on informal impressions (although they are important too).

Consider having the most skilled and experienced interviewers spend time demonstrating how they perform interviews to others.


答:
Console printing can work in many situations. This especially, if your code comes in small units instead of large blocks.

Another reason why debuggers are less of an issue in the Rails world is TDD. If you cut down your methods in small and testable items, you can write a complete set of tests for them and make sure they work for a given input. For me this eliminated the need for a debugger. Though this may of course depend on the kind of project. Very large or complex projects may demand to use different tools.

Title: What is a practical way to debug Rails?

Body:
I get the impression that in practice, debuggers are rarely used for Rails applications. (Likewise for other Ruby apps, as well as Python.)

We can compare this to the usual practice for  Java or VisualStudio programmers--they use an interactive debugger in a graphical IDE.

How do people debug Rails applications in practice? I am aware of the variety of debuggers, so no need to mention those, but do serious Rails programmers work without them? If so, why do you choose to do it this way?

It seems to me that console printing has its limits when debugging complex logic.


答:
I would say your interview process is at fault.

First, you need to train HR to do a better job of filtering resumes so that fewer bad ones get to the phone interview.

Next you need to sit down with the engineers who find good candidates and get them to create a standard list of questions that you use in every interview. The lists should be organized by the needs of different teams - you should have different questions for the group using C3 than for the database engineers, for instance.

Then you need to train everyone on how to interview and what to look for. People who have not had a lot of experience interviewing don't know how to find good candidates.

Create an interview checksheet that has the interviewer grade the interviewee on all the standard questions and add any notes.

Create a list of what is most important for different teams. We often interview for one position and recommend for a different one, but you can't do that unless you know what each group doing hiring needs.

Next assign the people to do the interviews that are most likely to be on the teams that get the new people. If team A is looking for a new engineer, current engineers on team A should be doing the phone screening. Now they have incentive to not hire a bozo as they personally will be working with him or her.

Pair up some of the more effective interviewers with some of the less effective so they can learn how it is done.

Management needs to put a priority on the activity. No one wants to work overtime because they had to do phone interviews. Just like engineers can get out of doing the laundry by deliberately turning shirts pink when forced to try, interviewers, who feel put upon because they have to make up the billable hours when faced with unbillable work, will do a bad job deliberately to avoid being reassigned that work. Make sure management knows that every engineer involved in interviewing is going to require some non-billable hours and should not be punished for not having 40 billable hours that week. Make sure employees know the job is important and they won't get hassled for spending time on it.

In the long run, no organization doing billable hours should assume that more than 32 hours a week will be billable (this is roughly the figure I used as a manpower specialist to calculate direct versus indirect time for all professions). If you are assuming more, you will miss deadlines and not be able to do work such as this which is critical to the long-term health of the organization.  The truth is that there is always non-billable work and non-billable time for things such as vacation, sick leave, jury duty, bereavement leave, etc. If you don't allow at least two hours a day for that in planning, you will miss deadlines - guaranteed. So if your teams are currently incorrectly estimating the work based on a 40 hours billable week, they need to fix that before the fix of the interview process will be effective.


问:
Should I provide synonyms in an API?
I'm designing a small library and there is a strong temptation to provide synonyms to some of the exported functions.

```<code>var foldl = function(){ ... };
var reduce = foldl; //reduce is a synonym for foldl
</code>```

I imagine that the multiple names might help the initial learnability of the API (since the user is more likely to stumble on the function he wants) but at the same time I worry the duplication will bring needless complexity.

What rules should I keep in mind when thinking about adding a synonym to a function in my API?

When whould I choose a "there is more then one way to do it" api and when should I incentivize there is one way to do it" instead?

答:
Don't provide multiple ways to do the same thing - that will just confuse the API users.

Having several names for the same things means you don't have a good name for it.

Title: Should I provide synonyms in an API?


问:
Question about Creating a Scripting Language
Say, for example, I wanted to pay somebody to create a programming language or scripting language for me. What type of document would they need, in order to fully understand what it is exactly that I want.

I mean, are there standard documents that describe the new programming/scripting language in question?

答:
99.9% of the time creating a new language is completely unnecessary. The return on investment would most likely be tiny, and you would have just wasted your time.

Most likely you can use Javascript as a susceptible scripting language, and there are parsers available for most languages already. You can also use other scripting languages you like if you can find a suitable parser for them. Implementing those into your program would require much less work and have a bigger return. People don't have to learn another language, they just have to learn your API.  Its a much better solution.

Creating a new language is almost always bad.


问:
New to iPhone Development - iOS5 Storyboard
I'm new here and pretty new to iOS development. My question is basically, should I learn the old school development methods or just learn how to do things using the latest tools (i.e. Storyboard)?

I've had a go with the Storyboard feature of XCode 4.2 and it's very powerful. My only concern is that it requires iOS 5. I don't mind learning the old way of doing things but I've been having trouble finding tutorials/examples for XCode 4.2 that don't use the storyboard.

An example would be the with my trouble finding a good tutorial on how to embed a Navigation Controller into a TabBarController. A lot of the material out there seems to be for older version of XCode. Using the storyboard I'm able to set this up with seconds but still haven't managed to get it working without it.

So in short :) would you guys suggest I continue my project using the Storyboard or make the extra effort to do things a little more manually?

答: Personally, I'd take the extra effort and learn how to do things programmatically. There are two camps in the IOS world - those who swear by using Interface Builder, and those who hate it and do everything in code. You will eventually wind up on one side of the fence or the other, but learning how to do stuff in code will only make you a better coder. I feel much more comfortable using tools such as IB and Storyboard when I have an idea of what's going on under the hood.</p>


问:
How to measure time lost due to environment problems?
I'm trying to determine how we can measure how much time the developers are loosing to poorly managed environment and inefficient ways-of-working.

The goals are:

Show managment how big the problem really is, in terms they can relate to. I.e $$$

Get a good baseline so that we can measure the progress.

Short background:

We manage the programming environment for 500 developers. This includes IDE (mainly Eclipse and Visual Studio), version control systems (ClearCase), what programs they have available.
Basically, everything related to the computer that involves programming.

Examples:

Not being able to work with tools they are used to due to strict security requirements.
Using version control system in a bad way causing problems when working in parallell.
Setting up project environment is done manually and different each time.
Using homecooked frameworks, rather than what are industry standard.
Building takes longer than needed due to homemade practices.
Deploying takes longer than needed due to homemade practices.

This does not include the actual coding pratices, project management or meetings. Sure, we can influence those things too, but for this questions those things are out of scope.

The question:

So, how can we determine how much time are lost due to the project environment?

The only thing I can think of to get some good data are polls and questionnaires.

Have anyone done something like this? What were the experiences and results?

Are there other literature or reasearch where I can get ideas from or compare results with?

Other questions exists regarding programmers inefficiency (like this), but those relate to coding practices and bugs.

答:
I assume you mean environment downtimes and lost productivity when development and test environments go down or need developer time to debug environment issues.

Make a simple tracking tool that is so easy to use that developers don't have to think about it.  Whenever an environment issue is being debugged by a developer, or they simply cannot work because of it, I had created a stopwatch like tool with something simple like AutoHotKeys (a tool that allows you to quickly and easily map key combinations to a script) that started a timer.  When the downtime was complete, hit the key combo again and AutoHotKeys send a simple GET request to a PHP page that I had set up on the webserver.  It just tallied up totals in milliseconds and stored them in a file.


问:
Is there an expiration date for well regarded, but old books on programming?
After reading a question about books every programmer should read, I wonder if the following should be considered obsolete:

Code complete: 1st edition in 1993; 2nd edition in May, 2004

Introduction to algorithms (Cormen, Leiserson, Rivest, Stein): 1st edition in 1990; 2nd edition in September, 2001; 3rd edition in 2009

The Pragmatic Programmer: October, 1999

Structure and Interpretation of Computer Programs: 1st edition in 1984; 2nd edition in September, 1996

The C Programming Language: 1st edition in 1978; 2nd edition in April, 1988

All these books seem very old. Isn't there a difference between modern computing and what was current when those book were written?

For example, my 61-year-old teacher explains things very nicely but forgets to take into account all that has been done between when he began to teach 25 years ago and now.

Isn't the same true for those books? Aren't there any more modern books that teach principles and technologies that are closer to current practice? Or do you consider them to be useful and relevant even today?

答:
I know what you mean, when we have advances (LINQ comes to mind) that change code readability and use, but simply because these books are old, does not mean that they don't offer great lessons for the reader.

While the programming languages they use may have fallen out of vogue, the theory behind the programming languages still rings true today. Most of these books make it a point to cover the basic very well, and the basics haven't changed all that much.


答: The "cloud" is not a factor. The "cloud" is actually much older than most of the books you listed. most of those books are about core principles, they don't really ever change to often. Frameworks and libraries change all the time, but how you should structure your code doesn't change much. Similarly a pointer is still a pointer it doesn't start doing different things just because. The only language specific book you listed is about C, in which case that old book is much more useful than anything new, because it was likely written closer to the time period that any C code you would be working with was developed.</p>

Title: Is there an expiration date for well regarded, but old books on programming?

Body:
After reading a question about books every programmer should read, I wonder if the following should be considered obsolete:

Code complete: 1st edition in 1993; 2nd edition in May, 2004

Introduction to algorithms (Cormen, Leiserson, Rivest, Stein): 1st edition in 1990; 2nd edition in September, 2001; 3rd edition in 2009

The Pragmatic Programmer: October, 1999

Structure and Interpretation of Computer Programs: 1st edition in 1984; 2nd edition in September, 1996

The C Programming Language: 1st edition in 1978; 2nd edition in April, 1988

All these books seem very old. Isn't there a difference between modern computing and what was current when those book were written?

For example, my 61-year-old teacher explains things very nicely but forgets to take into account all that has been done between when he began to teach 25 years ago and now.

Isn't the same true for those books? Aren't there any more modern books that teach principles and technologies that are closer to current practice? Or do you consider them to be useful and relevant even today?


答: The list you quoted, no they arent obsolete. A book is only obsolete when the subject has changed enough that they are not usefull. The nature of programming and the C language have both changed very little since publication</p>


答:
All those books seem very, very, very old."

Psychology-Computer-Programming (1971) - With a Million times as many programmers as in 1970 the psychology of how they design programs and what mistakes they make and how to avoid them is more important than ever.

Software Tools (1976) - With the web being a collection of frame works, utilities, scripts and plugins - the ideas in Software Tools have never been more relevant.

EDIT: To address the general question of - are old programming books relevant ?

The general principles of software engineering haven't changed all that much, there are new technologies OO, TDD etc.  But generally the users and the problems haven't changed - and thinking about how to divide up a problem is the same now as it always was.

These older books were generally written by experts in the field. Many modern programming books are aimed at rushing out a 2000page doorstop for the latest buzzword while it's still current.

Books on languages and technologies that are no longer used are probably not relevant - no Vax assembler manual is on the list. But 'C' is still very much used and 'The C programming langauge' is not only the best book on 'C' it's a model of how to write a concise tutorial and reference to your language.

Are there new algorithms? Yes. But all old the algorithms are still relevant and most of the new ones are in obscure areas that you are unlikely to meet. Nobody has come up with a better sort or FFT recently. Although other people have had attempts at explaining them better there is no reason that this year's Algorithms books is better than CLRS.

ps. Your cool new iWhatsit runs BSD, developed in 1977. Now you kids get off my lawn!


答:
Of the ones you mentioned "Code complete", "The pragmatic programmer" and "SICP" have been on my recommended-reading list for all new developers that start here at my company and want to get to a higher level.

They are not obsolete by a long shot because the fundamental science in Computer Science hasn't changed.


答:
These book are about the principles of development. These principles are, by nature, language-agnostic, and for some even paradigm-agnostic (OOP, functional programming, imperative languages).

They explain the theory and good ways of the development because, in the end, software is always about getting data, processing it, then outputting it back. Facebook, Twitter, 3D, batch process of accountancy, railway traffic management, launching rockets, etc.

Books that are about a language, like  "How to learn XXXXX in YY days", where XXXXX is a language and YY is a number that will eventually (and sometimes actually very quickly) become obsolete, because, by nature, they are about things that either evolve, or get replaced and become outdated.

Code Complete, by the awesome Steve McConnell, is perhaps the book that made me realize this. And the Pragmatic Programmer totally changed the vision I had of software development. By reading such books, you realize that 95% of the problem you're facing everyday has already been solved, and that 95% of us are still reinventing the wheel.

The so-called "Cloud" isn't the future of software development, it's a way to use developed software.

Don't fall into the trap of hype/bullshit buzzwords, focus on how you can improve your software craftsman skills.

Focus on learning from what other brilliant spirits have invented and learned before us, because it is the only way to become an accomplished developer.


答:
I have not read all those books, but I do own Code Complete and The Pragmatic Programmer. These books are far from being obsolete. They might have a couple of paragraphs that are a bit rusty but most of the content is still relevant today.

The advance in Computer Science and Programming is an evolutionary process. New abstractions are being introduced on top of old ones but these new things do not necessary make the old obsolete.

An analogy... Whether you are studying to be a trauma surgeon or a surgeon who specializes in heart transplantation, you still need to know how the human body works, cell chemistry, organ systems, how to open up the chest and how to quickly stop bleeding if it occurs, etc... Just because they invented endoscopic equipment and less invasive techniques, it does not mean you are off the hook for learning the basics. It only means you have to learn more.


问:
Can you successfully keep managing when you are forced back into development?
For about eight months I managed a development team doing a re-write of a web based application. During this time, I was focused on many aspects of the project that did not involve directly writing code, even though by trade that's what I started out as.

Recently the number of developers assigned to the project has dropped and I am now forced to drop back into a developer/management role. Since that time I have found that it's very difficult to focus on a feature and get it completed while at the same time trying to stay ahead of the other developers and make sure that we're keeping on track.

My questions is this: can you successfully keep managing a project when you are forced back into development?

答:
No, unless you plan on doing your development outside of work hours, you can't do everything.

Do you all share with each other what you are working on each day as well as progress, that way you can all shift priorities as needed until you increase the number of developers.


答:
I had a very similar problem. A management job that wasn't 100%-consuming, but if I tried to do development work with the rest of my time then I became a bottleneck, owing largely to not being able to focus on a single development task for more than a couple of hours at a time.

My advice is to stop doing that and start spending that spare time clearing the road for the other developers. Look at anything which costs development time and ask what you can do about it. Have a read of Continuous Delivery and see what you can do to improve your build and release process. Have a look at your unit and integration test coverage.

Just avoid working on tasks that are part of the iteration unless you're sure you can complete them smoothly without becoming a bottleneck. As long as you can point to an improvement in the amount of work being done, no one's going to care about the details of how you spent your time.

Title: Can you successfully keep managing when you are forced back into development?

Body:
For about eight months I managed a development team doing a re-write of a web based application. During this time, I was focused on many aspects of the project that did not involve directly writing code, even though by trade that's what I started out as.

Recently the number of developers assigned to the project has dropped and I am now forced to drop back into a developer/management role. Since that time I have found that it's very difficult to focus on a feature and get it completed while at the same time trying to stay ahead of the other developers and make sure that we're keeping on track.

My questions is this: can you successfully keep managing a project when you are forced back into development?


答:
You know the saying "can't see the forest for the trees". When you're managing, your job is to tend the forest. When you're writing code, your job is to grow a tree. I've found that when I take my hands off code, I'm a better manager. I'm able to interact with my team and keep the pulse of the project. The second I drop down to writing code, that high level view has to go away or I won't be an effective coder.

I don't know a way around this, you can't manage a team and write code at the same time. One or the other of those tasks will suffer as a result.


答: Just use one. The only situation I can think of where you may want both is if there are two separate business domains that just happen to require the same function at this time, but they could split later. I know that's YAGNI, but if they are 'considering' it at this time, you may want to think about it.</p>

Title: Should I provide synonyms in an API?

Body:
I'm designing a small library and there is a strong temptation to provide synonyms to some of the exported functions.

```<code>var foldl = function(){ ... };
var reduce = foldl; //reduce is a synonym for foldl
</code>```

I imagine that the multiple names might help the initial learnability of the API (since the user is more likely to stumble on the function he wants) but at the same time I worry the duplication will bring needless complexity.

What rules should I keep in mind when thinking about adding a synonym to a function in my API?

When whould I choose a "there is more then one way to do it" api and when should I incentivize there is one way to do it" instead?