问:
Ring of numbers where adjacent entries sum up to a prime
Given a number n, find a permutation of the numbers 1...n such that all adjacent entries sum up to primes. If such a permutation does not exist, throw an error.

Is there a purely-functional way to do this problem? The solution, which apparently uses backtracking, given uses C++, a language which I am not very familiar with, and loops in loops in loops with very badly-named variable names and a whole lot of mutation. Even if the solution requires mutation, nested loops are really difficult to translate into Racket, the language I currently use.

A more general question would be, how to do backtracking algorithms purely functionally when the concept of backtracking seems to always involve maintaining a state of where you are currently and a big history breadcrumb global state variable that keeps getting mutated?

Of course the dumb way would be to generate all permutations and test them one by one, but are there more efficient ways, preferably implementing a backtracking method, to do so functionally?

Since I use Racket, the solution might not be purely functional but preferably mostly functional, i.e. no repeatedly mutating counter vars in loops or such.

答:
I just wrote an implementation in Clojure, a functional Lisp-I, which you may find below. Because of the controversy in the commments to this answer, I will try to explain the code and the techniques used to achieve the result as good as possible, especially for those who are not Clojurists. Forgive me if I don't touch on everything in great detail and length.

This version does not mutate state. All of Clojures values are immutable, e. g. a vector [1 2] can not be altered once it has been constructed. When you want to concat that vector with another vector [3 4] you may invoke a function like
concat like this (concat [1 2] [3 4]). Concat will return a new vector [1 2 3 4] and the two input vectors will be forgotten. The great thing is that behind the scenes, structural sharing is happening: The new vector [1 2 3 4] consists of the same data [1 2] and [3 4] consisted of. Also, if we had bound the vector [1 2] to a symbol a instead, after (concat a [3 4]) a would still be [1 2]. So while you are always generating new immutable values, in memory only the delta will be allocated.

One other feature of Clojure I am taking advantage of is laziness. E. g. you can build a sequence of all number 0 ... n with (range). The call to range returns an infinite sequence like (0 1 2 3 4 5...), but it is not realized until elements of it are consumed. Finally, many transformation functions return new lazy-sequences from lazy input sequences, so (filter even? (range)) would give me a lazy sequence of all numbers >= 0 for which the predicate even? (a boolean function) returns true - however, the filtering only happens when I actually consume elements from that sequence, e. g. (take 3 (filter even? (range))) will return (0 2 4): Until here, filter has been invoked five times (as many times as necessary to produce three elements or have the input sequence consumed).

The prime ring generator below utilizes this laziness. If you invoke (rings-of-primes 100) it immediately returns a lazy sequence of all possible prime rings with 100 elements from 1 to 100. Nothing is calculated, so if I wanted to have only three rings, I could do (take 3 (rings-of-primes 100)) and calculation would only happen for the production of three rings.

The core to the solution below is the function helper-fn which is defined within rings-of-primes. It takes two immutable values as arguments and refers to two other immutable values, length (the argument to rings-of-primes) and n-range (defined in rings-of-primes as seq [1 .. length]) in its body.

The two arguments to helper-fn are used, an immutable set of numbers that have been used in the possible ring passed as the second arg, acc (short for accumulator).

One of the great advantages of Clojure is that when you are dealing with immutable values, it's quite easy to write pure functions. helper-fn is one of those pure functions. It is defined as follows: It takes the input of a set of used numbers, and a vector of numbers which is supposed to be a partial ring of primes, and always returns a sequence of possible rings of primes that begin with the numbers in acc and have a size of length. If no rings are possible, helper-fn returns (), an empty list (not the same as nil in Clojure).

```<code>          (let [last-elem (peek acc)]
            (if (and (= length (count acc))
                     (is-prime?
                      (+ last-elem
                         (first acc))))
              [acc]
</code>```

In the above code-snippet (the first lines of helper-fn), the symbol last-elem is bound to the last value of acc. Then within the conditional statement if two conditions are tested: 1. Has accumulator the user-desired length ((= length (count acc)))?, 2. Do the last and the first element add up to a prime number. If both conditions are matched, helper-fn returns [acc], a vector with exactly one element: The accumulator, a valid prime-ring. The nesting in an additional vector is needed because our function is supposed to return a sequence of valid prime-rings, not just a sequence of numbers.

Now what happens if the passed value is not a prime-ring, like when the function is invoked the first time within rings-of-primes: (helper-fn #{1} [1]). As you might have noticed, #{1} is the notation for a set, and within helper-fn, used will now be bound to #{1} and acc will be bound to [1].

Given that we have asked for a length of 4, the test-clause in the code snippet above will fail. What happens then?

```<code>              (let [parity-filter (if (even? last-elem)
                                    odd?
                                    even?)]
                (->> n-range
                     (filter #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem))))
                     (lazy-mapcat #(helper-fn
                                    (conj used %)
                                    (conj acc %))))))))]
</code>```

The parity-filter symbol will be bound to either the predicate function odd? or to the predicate function even?, depending on whether the last-element of acc is even or odd. The reason is that you can divide even numbers by two, and adding two even numbers or two odd numbers always results in an even number which can't be a prime number then. So we only want the numbers with the opposite parity of the last element of acc, last-elem.

->> is an awesome macro. It does not do anything except for reordering the code you put into it. That is one of the advantages of Clojure being a lisp, that all your code is data that can be manipulated before evaluation. ->> reorders your code so (->> x (doY) (doZ baz)) => (doZ baz (doY x)). In other words, the first argument is appended to the end of the second form, which is appended to the end of the third form and so on.

So in this case, n-range, which was generated at the beginning of rings-of-primes, another immutable value, will be threaded with ->>. n-range will always be a sequence [1 .. length]. Now this sequence must be filtered. We define a small function, a lambda, on the fly as the first argument to filter:

```<code>                             #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem)))
</code>```

In this case #(...) creates a function with one argument to which we refer as %. E. g. #(+ % %) would create a function that takes one argument and doubles it.
Our lambda is a predicate function that tests the argument for three conditions: 1. It must pass the parity-filter, 2. It may not be in the set used (you can invoke sets like functions and they return whether they contain the argument), 3. Added to the last-elem of acc, it must be a prime-number. If this three conditions match, it is a possible candidate for the next iteration of the prime ring we are building, and it will be part of the lazy sequence returned by the filter expression.

After that, a function lazy-mapcat that comes with this source, is invoked. It takes a transformation function and a sequence of elements (our filtered candidates), transforms each input element with the transform function and concats the returned value (a sequence) to the other returned values. The transformation function may return any kind of sequence, also the empty sequence. Let's have a closer look at the transformation function:

```<code>                                 #(helper-fn
                                    (conj used %)
                                    (conj acc %))
</code>```

Yes! It's a call to helper-fn itself. conj takes a collection and an argument and returns a new collection with that argument in it. Here we put the value taken from our filtered sequence into a new version of used, also create a new version of acc with that number in it, and pass them to helper-fn. Now go back to line 1. helper-fn will then (after many more recursive steps) return a sequence of possible prime-rings and because of mapcat we do that for each candidate that may be the next valid number in the current prime-ring. All the resulting sequences of rings will be concatenated to one sequence of rings. Of course, in some cases helper-fn will return an empty list, and on a higher level, that empty list will be concataned with other lists - also within a mapcat expression.

As you can see, no state is mutated. The resulting function is pure and can also be invoked with odd lengths or negative input values, in which case it will (mathematically correctly) return an empty list as a result.

You could say that the backtracking happens with acc passed to helper-fn, but much more I'd like to think of this implementation of a pure function call that results in the self assembly of possible prime-rings through a series of recursive function calls.

```<code>;; Clojure implementation of http://coj.uci.cu/24h/problem.xhtml?abb=1196
;; This version generates all possible rings of primes for any given n
;; Leon Grapenthin, Nov. 14 2013

(def is-prime?
  "Returns true if n is a prime number. Memoized."
  (memoize              ;; remember all results returned by this function
                        ;; so that a second call with the same n does not
                        ;; require calculation
   (fn is-prime?
     [n]
     (cond
      (even? n) (= 2 n) ;; if n is even, return whether
                        ;; its 2, the only even prime number
      (= 1 n) false     ;; if n is one, return false
      :otherwise
      (->> (range 2 n)  ;; build a sequence from 2 to n
           (filter (comp zero?
                         (partial mod n))) ;; filter those were dividing
                                           ;; n by them has a rest of 0
           empty?))))) ;; none could be found? => It's a prime number.

(defn lazy-mapcat
  ;; stolen from http://clojurian.blogspot.de/2012/11/beware-of-mapcat.html
  [f coll]
  (lazy-seq
   (if (not-empty coll)
     (concat
      (f (first coll))
      (lazy-mapcat f (rest coll))))))

(defn rings-of-primes
  "Returns a lazy sequence of possible prime rings for length."
  [length]
  (let [n-range (range 1 (inc length))
        helper-fn
        (fn helper-fn
          ;; tries to build the seq until acc has length and the ring
          ;; condition is fulfilled, otherwise returns nil
          [used acc]
          (let [last-elem (peek acc)]
            (if (and (= length (count acc))
                     (is-prime?
                      (+ last-elem
                         (first acc))))
              [acc]
              (let [;; slight optimization: a prime number (+ x y) with
                    ;; (not= x y) can only be built when the parities of
                    ;; x and y differ:
                    parity-filter (if (even? last-elem)
                                    odd?
                                    even?)]
                (->> n-range
                     (filter #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem))))
                     (lazy-mapcat #(helper-fn
                                    (conj used %)
                                    (conj acc %))))))))]
    (helper-fn #{1} [1])))

;; (time
;;  (first (rings-of-primes 100)))
;; "Elapsed time: 57.316798 msecs"
;; [1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19 22
;;  21 20 23 24 29 30 31 28 25 34 27 26 33 38 35 32 39
;;  40 43 36 37 42 41 48 49 52 45 44 53 50 47 54 55 46
;;  51 56 57 70 61 66 65 62 69 58 73 64 63 68 59 72 67
;;  60 71 78 79 84 83 74 75 76 81 82 85 88 91 90 89 92
;;  87 80 77 86 93 98 95 96 97 94 99 100]
</code>```

Body:
I just wrote an implementation in Clojure, a functional Lisp-I, which you may find below. Because of the controversy in the commments to this answer, I will try to explain the code and the techniques used to achieve the result as good as possible, especially for those who are not Clojurists. Forgive me if I don't touch on everything in great detail and length.

This version does not mutate state. All of Clojures values are immutable, e. g. a vector [1 2] can not be altered once it has been constructed. When you want to concat that vector with another vector [3 4] you may invoke a function like
concat like this (concat [1 2] [3 4]). Concat will return a new vector [1 2 3 4] and the two input vectors will be forgotten. The great thing is that behind the scenes, structural sharing is happening: The new vector [1 2 3 4] consists of the same data [1 2] and [3 4] consisted of. Also, if we had bound the vector [1 2] to a symbol a instead, after (concat a [3 4]) a would still be [1 2]. So while you are always generating new immutable values, in memory only the delta will be allocated.

One other feature of Clojure I am taking advantage of is laziness. E. g. you can build a sequence of all number 0 ... n with (range). The call to range returns an infinite sequence like (0 1 2 3 4 5...), but it is not realized until elements of it are consumed. Finally, many transformation functions return new lazy-sequences from lazy input sequences, so (filter even? (range)) would give me a lazy sequence of all numbers >= 0 for which the predicate even? (a boolean function) returns true - however, the filtering only happens when I actually consume elements from that sequence, e. g. (take 3 (filter even? (range))) will return (0 2 4): Until here, filter has been invoked five times (as many times as necessary to produce three elements or have the input sequence consumed).

The prime ring generator below utilizes this laziness. If you invoke (rings-of-primes 100) it immediately returns a lazy sequence of all possible prime rings with 100 elements from 1 to 100. Nothing is calculated, so if I wanted to have only three rings, I could do (take 3 (rings-of-primes 100)) and calculation would only happen for the production of three rings.

The core to the solution below is the function helper-fn which is defined within rings-of-primes. It takes two immutable values as arguments and refers to two other immutable values, length (the argument to rings-of-primes) and n-range (defined in rings-of-primes as seq [1 .. length]) in its body.

The two arguments to helper-fn are used, an immutable set of numbers that have been used in the possible ring passed as the second arg, acc (short for accumulator).

One of the great advantages of Clojure is that when you are dealing with immutable values, it's quite easy to write pure functions. helper-fn is one of those pure functions. It is defined as follows: It takes the input of a set of used numbers, and a vector of numbers which is supposed to be a partial ring of primes, and always returns a sequence of possible rings of primes that begin with the numbers in acc and have a size of length. If no rings are possible, helper-fn returns (), an empty list (not the same as nil in Clojure).

          (let [last-elem (peek acc)]
            (if (and (= length (count acc))
                     (is-prime?
                      (+ last-elem
                         (first acc))))
              [acc]

In the above code-snippet (the first lines of helper-fn), the symbol last-elem is bound to the last value of acc. Then within the conditional statement if two conditions are tested: 1. Has accumulator the user-desired length ((= length (count acc)))?, 2. Do the last and the first element add up to a prime number. If both conditions are matched, helper-fn returns [acc], a vector with exactly one element: The accumulator, a valid prime-ring. The nesting in an additional vector is needed because our function is supposed to return a sequence of valid prime-rings, not just a sequence of numbers.

Now what happens if the passed value is not a prime-ring, like when the function is invoked the first time within rings-of-primes: (helper-fn #{1} [1]). As you might have noticed, #{1} is the notation for a set, and within helper-fn, used will now be bound to #{1} and acc will be bound to [1].

Given that we have asked for a length of 4, the test-clause in the code snippet above will fail. What happens then?

              (let [parity-filter (if (even? last-elem)
                                    odd?
                                    even?)]
                (->> n-range
                     (filter #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem))))
                     (lazy-mapcat #(helper-fn
                                    (conj used %)
                                    (conj acc %))))))))]

The parity-filter symbol will be bound to either the predicate function odd? or to the predicate function even?, depending on whether the last-element of acc is even or odd. The reason is that you can divide even numbers by two, and adding two even numbers or two odd numbers always results in an even number which can't be a prime number then. So we only want the numbers with the opposite parity of the last element of acc, last-elem.

->> is an awesome macro. It does not do anything except for reordering the code you put into it. That is one of the advantages of Clojure being a lisp, that all your code is data that can be manipulated before evaluation. ->> reorders your code so (->> x (doY) (doZ baz)) => (doZ baz (doY x)). In other words, the first argument is appended to the end of the second form, which is appended to the end of the third form and so on.

So in this case, n-range, which was generated at the beginning of rings-of-primes, another immutable value, will be threaded with ->>. n-range will always be a sequence [1 .. length]. Now this sequence must be filtered. We define a small function, a lambda, on the fly as the first argument to filter:

                             #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem)))

In this case #(...) creates a function with one argument to which we refer as %. E. g. #(+ % %) would create a function that takes one argument and doubles it.
Our lambda is a predicate function that tests the argument for three conditions: 1. It must pass the parity-filter, 2. It may not be in the set used (you can invoke sets like functions and they return whether they contain the argument), 3. Added to the last-elem of acc, it must be a prime-number. If this three conditions match, it is a possible candidate for the next iteration of the prime ring we are building, and it will be part of the lazy sequence returned by the filter expression.

After that, a function lazy-mapcat that comes with this source, is invoked. It takes a transformation function and a sequence of elements (our filtered candidates), transforms each input element with the transform function and concats the returned value (a sequence) to the other returned values. The transformation function may return any kind of sequence, also the empty sequence. Let's have a closer look at the transformation function:

                                 #(helper-fn
                                    (conj used %)
                                    (conj acc %))

Yes! It's a call to helper-fn itself. conj takes a collection and an argument and returns a new collection with that argument in it. Here we put the value taken from our filtered sequence into a new version of used, also create a new version of acc with that number in it, and pass them to helper-fn. Now go back to line 1. helper-fn will then (after many more recursive steps) return a sequence of possible prime-rings and because of mapcat we do that for each candidate that may be the next valid number in the current prime-ring. All the resulting sequences of rings will be concatenated to one sequence of rings. Of course, in some cases helper-fn will return an empty list, and on a higher level, that empty list will be concataned with other lists - also within a mapcat expression.

As you can see, no state is mutated. The resulting function is pure and can also be invoked with odd lengths or negative input values, in which case it will (mathematically correctly) return an empty list as a result.

You could say that the backtracking happens with acc passed to helper-fn, but much more I'd like to think of this implementation of a pure function call that results in the self assembly of possible prime-rings through a series of recursive function calls.

;; Clojure implementation of http://coj.uci.cu/24h/problem.xhtml?abb=1196
;; This version generates all possible rings of primes for any given n
;; Leon Grapenthin, Nov. 14 2013

(def is-prime?
  "Returns true if n is a prime number. Memoized."
  (memoize              ;; remember all results returned by this function
                        ;; so that a second call with the same n does not
                        ;; require calculation
   (fn is-prime?
     [n]
     (cond
      (even? n) (= 2 n) ;; if n is even, return whether
                        ;; its 2, the only even prime number
      (= 1 n) false     ;; if n is one, return false
      :otherwise
      (->> (range 2 n)  ;; build a sequence from 2 to n
           (filter (comp zero?
                         (partial mod n))) ;; filter those were dividing
                                           ;; n by them has a rest of 0
           empty?))))) ;; none could be found? => It's a prime number.

(defn lazy-mapcat
  ;; stolen from http://clojurian.blogspot.de/2012/11/beware-of-mapcat.html
  [f coll]
  (lazy-seq
   (if (not-empty coll)
     (concat
      (f (first coll))
      (lazy-mapcat f (rest coll))))))

(defn rings-of-primes
  "Returns a lazy sequence of possible prime rings for length."
  [length]
  (let [n-range (range 1 (inc length))
        helper-fn
        (fn helper-fn
          ;; tries to build the seq until acc has length and the ring
          ;; condition is fulfilled, otherwise returns nil
          [used acc]
          (let [last-elem (peek acc)]
            (if (and (= length (count acc))
                     (is-prime?
                      (+ last-elem
                         (first acc))))
              [acc]
              (let [;; slight optimization: a prime number (+ x y) with
                    ;; (not= x y) can only be built when the parities of
                    ;; x and y differ:
                    parity-filter (if (even? last-elem)
                                    odd?
                                    even?)]
                (->> n-range
                     (filter #(and (parity-filter %)
                                   (not (used %))
                                   (is-prime? (+ %
                                                 last-elem))))
                     (lazy-mapcat #(helper-fn
                                    (conj used %)
                                    (conj acc %))))))))]
    (helper-fn #{1} [1])))

;; (time
;;  (first (rings-of-primes 100)))
;; "Elapsed time: 57.316798 msecs"
;; [1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 18 19 22
;;  21 20 23 24 29 30 31 28 25 34 27 26 33 38 35 32 39
;;  40 43 36 37 42 41 48 49 52 45 44 53 50 47 54 55 46
;;  51 56 57 70 61 66 65 62 69 58 73 64 63 68 59 72 67
;;  60 71 78 79 84 83 74 75 76 81 82 85 88 91 90 89 92
;;  87 80 77 86 93 98 95 96 97 94 99 100]


问:
Is there any "real" reason multiple inheritance is hated?
I've always liked the idea of having multiple inheritance supported in a language.  Most often though it's intentionally forgone, and the supposed "replacement" is interfaces.  Interfaces simply do not cover all the same ground multiple inheritance does, and this restriction can occasionally lead to more boilerplate code.

The only basic reason I have ever heard for this is the diamond problem with base classes.  I just can't accept that.  To me, it comes off an awful lot like, "Well, it's possible to screw it up, so it's automatically a bad idea."  You can screw up anything in a programming language though, and I mean anything.  I just cannot take this seriously, at least not without a more thorough explanation.

Just being aware of this problem is 90% of the battle.  Furthermore I think I heard something years ago about a general-purpose work-around involving an "envelope" algorithm or something like that (does this ring a bell, anyone?).

Concerning the diamond problem, the only potentially genuine problem I can think of is if you're trying to use a third-party library and can't see that two seemingly unrelated classes in that library have a common base class, but in addition to documentation, a simple language feature could, let's say, require that you specifically declare your intent to create a diamond before it'll actually compile one for you.  With such a feature, any creation of a diamond is either intentional, reckless, or because one is unaware of this pitfall.

So that all being said...Is there any real reason most people hate multiple inheritance, or is it all just a bunch of hysteria that causes more harm than good?  Is there something that I am not seeing here?  Thank you.

Example

Car extends WheeledVehicle, KIASpectra extends Car and Electronic, KIASpectra contains Radio.  Why doesn't KIASpectra contain Electronic?

Because it is an Electronic.  Inheritance vs. composition should always be an is-a relationship vs. a has-a relationship.

Because it is an Electronic.  There are wires, circuit boards, switches, etc. all up and down that thing.

Because it is an Electronic.  If your battery goes dead in the winter, you're in just as much trouble as if all your wheels suddenly went missing.

Why not use interfaces?  Take #3, for instance.  I don't want to write this over and over again, and I really don't want to create some bizarre proxy helper class to do this either:

private void runOrDont()
{
    if (this.battery)
    {
        if (this.battery.working && this.switchedOn)
        {
            this.run();
            return;
        }
    }
    this.dontRun();
}
```

(We're not getting into whether that implementation is good or bad.)  You can imagine how there may be several of these functions associated with Electronic that are not related to anything in WheeledVehicle, and vice-versa.

I wasn't sure whether to settle down on that example or not, since there is room for interpretation there.  You could also think in terms of Plane extending Vehicle and FlyingObject and Bird extending Animal and FlyingObject, or in terms of a much purer example.

答:
The only reason why it is disallowed is because it makes it easy for people to shoot themselves in the foot.

What usually follows in this sort of a discussion is arguments as to whether the flexibility of having the tools is more important than the safety of not shooting off your foot. There is no decidedly correct answer to that argument, because like most other things in programming, the answer depends on context.

If your developers are comfortable with MI, and MI makes sense in the context of what you are doing, then you will sorely miss it in a language that doesn't support it. At the same time if the team is not comfortable with it, or there is no real need for it and people use it 'just because they can', then that is counter-productive.

But no, there does not exist an all-convincing absolutely true argument that proves multiple inheritance to be a bad idea.

EDIT

Answers to this question appear to be unanimous. For the sake of being the devil's advocate I will provide a good example of multiple inheritance, where not doing it leads to hacks.

Suppose you are designing a capital markets application. You need a data model for securities. Some securities are equity products (stocks, real estate investment trusts, etc) others are debt (bonds, corporate bonds), others are derivatives (options, futures).
So if you're avoiding MI, you will make a very clear, simple inheritance tree. A Stock will inherit Equity, Bond will inherit Debt. Great so far, but what about derivatives? They can be based off of Equity-like products or Debit-like products? Ok, I guess we will make our inheritance tree branch out more. Keep in mind, some derivatives are based off of equity products, debt products, or neither. So our inheritance tree is getting complicated.
Then along comes the business analyst and tells you that now we support indexed securities (index options, index future options). And these things can be based off of Equity, Debt, or Derivative. This is getting messy! Does my index future option derive Equity->Stock->Option->Index? Why not Equity->Stock->Index->Option? What if one day I find both in my code (This happened; true story)?

The problem here is that these fundamental types can be mixed in any permutation that does not naturally derive one from the other. The objects are defined by an is a relationship, so composition makes no sense whatsoever. Multiple inheritance (or the similar concept of mixins) is the only logical representation here.

The real solution for this problem is to have the Equity, Debt, Derivative, Index types defined and mixed using multiple inheritance to create your data model. This will create objects that both, make sense, and lend easily to code re-use.

ContentLicense: CC BY-SA 3.0


答:
Inheritance, multiple or otherwise, is not that important.  If two objects of different type are substitutable, that is what matters, even if they are not linked by inheritance.

A linked list and a character string have little in common, and need not be linked by inheritance, but it's useful if I can use a length function to get the number of elements in either one.

Inheritance is a trick to avoid repeated implementation of code. If inheritance saves you work, and multiple inheritance saves you even more work compared to single inheritance, then that's all the justification that is needed.

I suspect that some languages do not implement multiple inheritance very well, and to the practitioners of those languages, that is what multiple inheritance means. Mention multiple inheritance to a C++ programmer, and what comes to mind is something about issues when a class ends up with two copies of a base via two different inheritance paths, and whether to use virtual on a base class, and confusion about how destructors are called, and so on.

In many languages, inheritance of class is conflated with inheritance of symbols. When you derive a class D from a class B, not only are you creating a type relationship, but because these classes also serve as lexical namespaces, you are dealing with the importation of symbols from the B namespace to the D namespace, in addition to the semantics of what is happening with the types B and D themselves. Multiple inheritance therefore brings in issues of symbol clashing. If we inherit from card_deck and graphic, both of which "have" a draw method, what does it mean to draw the resulting object?  An object system which doesn't have this problem is the one in Common Lisp. Perhaps not coincidentally, multiple inheritance gets used in Lisp programs.

Badly implemented, inconvenient anything (such as multiple inheritance) should be hated.

Title: Is there any "real" reason multiple inheritance is hated?

Body:
I've always liked the idea of having multiple inheritance supported in a language.  Most often though it's intentionally forgone, and the supposed "replacement" is interfaces.  Interfaces simply do not cover all the same ground multiple inheritance does, and this restriction can occasionally lead to more boilerplate code.

The only basic reason I have ever heard for this is the diamond problem with base classes.  I just can't accept that.  To me, it comes off an awful lot like, "Well, it's possible to screw it up, so it's automatically a bad idea."  You can screw up anything in a programming language though, and I mean anything.  I just cannot take this seriously, at least not without a more thorough explanation.

Just being aware of this problem is 90% of the battle.  Furthermore I think I heard something years ago about a general-purpose work-around involving an "envelope" algorithm or something like that (does this ring a bell, anyone?).

Concerning the diamond problem, the only potentially genuine problem I can think of is if you're trying to use a third-party library and can't see that two seemingly unrelated classes in that library have a common base class, but in addition to documentation, a simple language feature could, let's say, require that you specifically declare your intent to create a diamond before it'll actually compile one for you.  With such a feature, any creation of a diamond is either intentional, reckless, or because one is unaware of this pitfall.

So that all being said...Is there any real reason most people hate multiple inheritance, or is it all just a bunch of hysteria that causes more harm than good?  Is there something that I am not seeing here?  Thank you.

Example

Car extends WheeledVehicle, KIASpectra extends Car and Electronic, KIASpectra contains Radio.  Why doesn't KIASpectra contain Electronic?

Because it is an Electronic.  Inheritance vs. composition should always be an is-a relationship vs. a has-a relationship.

Because it is an Electronic.  There are wires, circuit boards, switches, etc. all up and down that thing.

Because it is an Electronic.  If your battery goes dead in the winter, you're in just as much trouble as if all your wheels suddenly went missing.

Why not use interfaces?  Take #3, for instance.  I don't want to write this over and over again, and I really don't want to create some bizarre proxy helper class to do this either:

private void runOrDont()
{
    if (this.battery)
    {
        if (this.battery.working && this.switchedOn)
        {
            this.run();
            return;
        }
    }
    this.dontRun();
}
```

(We're not getting into whether that implementation is good or bad.)  You can imagine how there may be several of these functions associated with Electronic that are not related to anything in WheeledVehicle, and vice-versa.

I wasn't sure whether to settle down on that example or not, since there is room for interpretation there.  You could also think in terms of Plane extending Vehicle and FlyingObject and Bird extending Animal and FlyingObject, or in terms of a much purer example.


问:
How to configure these REST API Resources
I'm still in the design phase of my REST API, and I'm a bit stuck on how to configure the resources. The API will be consumed by mobile devices (Android, iOS, and Windows). Communication through HTTPS.

These are the features the API will support:

View a list of previous reservations

View a previous reservation

Create a new reservation

Create a new anonymous reservation

I was thinking of naming my resources as following:

api/users/{id}/reservations (GET)

api/users/{id}/reservations/{id} (GET)

api/users/{id}/reservations (POST)

api/users/0/reservations (POST)

I'm not sure if the resource for 4 is a good design?

Also 1, 2, 3 require a user to have an account and be authenticated. Authentication will be done using an access-token. This means the user has to log in every X period.

Is it bad to store the user id on the device so it is able to perform requests where the user id is required? Or should I just remove the /users/ part from the resource and have the server decide based on the access-token which user is trying to perform a specific action?

The REST API will be built using ASP.NET MVC4.

答:
What is your application about? Reservations or users?

The fact that reservations can be made anonymously is a dead give away that your application is about reservations and that users are "just" a way to make it easier for return visitors to make a reservation (not having to fill in their details again).

As reservations can obviously exist without a user, there should be no need to fake a user when posting a reservation.

All this leads to the inevitable conclusion that reservations should come first. And that your URI's should reflect that.

Posting an anonymous reservation is then as easy as pie:

POST to /api/reservations

And posting a reservation by a specific user can also be handled by this URI. The user id of the logged in user id is already known by other means and it should not be necessary to repeat it in the URI. How would you like it when I as a logged in user make a reservation using your user id (which could be easily gleaned from the URI's) and thus have your credit card charged?

Putting reservations first when it comes to retrieving them leads to URI's like these:

GET to /api/reservations

for all reservations by the logged in user, and for reservations made by a user other than the logged in user, you could have

GET to /api/reservations/users/{id}, or

GET to /api/reservations?user={id}

Getting reservations made by someone other than the logged in user should probably be a feature restricted to administrators. As such it sounds more like filtering/search.

While using URI scopes to filter is quite acceptable, it does carry the limitation that adding fields on which to filter can become a pain. Using query parameters is a more natural fit for filter criteria, with the added benefit will be a lot easier to extend the number of fields that can be used as filter criteria.


答:
The other answers here seem to be getting mostly into theory.  So here's a concrete Python example, simplified down, that I've actually smashed headlong into, which required a fair amount of refactoring:

class Foo(object):
   def zeta(self):
      print "foozeta"

class Bar(object):
   def zeta(self):
      print "barzeta"

   def barstuff(self):
      print "barstuff"
      self.zeta()

class Bang(Foo, Bar):
   def stuff(self):
      self.zeta()
      print "---"
      self.barstuff()

z = Bang()
z.stuff()
```

<p><code>Bar</code> was written assuming it had its own implementation of <code>zeta()</code>, which is generally a pretty good assumption.  A subclass should override it as appropriate so that it does the right thing.  Unfortunately, the names were only coincidentally the same - they did rather different things, but <code>Bar</code> was now calling <code>Foo</code>'s implementation:</p>

```foozeta
---
barstuff
foozeta
```

It is rather frustrating when there are no errors thrown, the application starts acting just ever so slightly wrong, and the code change that caused it (creating Bar.zeta) doesn't seem to be where the problem lies.

Body:
The other answers here seem to be getting mostly into theory.  So here's a concrete Python example, simplified down, that I've actually smashed headlong into, which required a fair amount of refactoring:

class Foo(object):
   def zeta(self):
      print "foozeta"

class Bar(object):
   def zeta(self):
      print "barzeta"

   def barstuff(self):
      print "barstuff"
      self.zeta()

class Bang(Foo, Bar):
   def stuff(self):
      self.zeta()
      print "---"
      self.barstuff()

z = Bang()
z.stuff()

Bar was written assuming it had its own implementation of zeta(), which is generally a pretty good assumption.  A subclass should override it as appropriate so that it does the right thing.  Unfortunately, the names were only coincidentally the same - they did rather different things, but Bar was now calling Foo's implementation:

foozeta
---
barstuff
foozeta

It is rather frustrating when there are no errors thrown, the application starts acting just ever so slightly wrong, and the code change that caused it (creating Bar.zeta) doesn't seem to be where the problem lies.


问:
Should I start a project I am hoping to recruit others to?
I have an idea for a program that I think is a good one (Don't we all?).  I am an amateur programmer and would like to recruit some more advanced programmers onto the project since there are some aspects that I am not skilled enough to do myself.  Is it better to

a) Develop the software on my own as much as I can, even though it will be amateurish, and then show a demo to potential recruits

or

b) Try and recruit some more advanced programmers and seek their advice and guidance before I get started so that it is done correctly from the beginning?

I would especially love it if someone has any experience of being in a similar position, but sage speculation is welcome too.

答:
Ideas are cheap.

Nobody is going to care that you have a good idea (or at least think you do).

Unless you have money to throw around, you are not going to interest an advanced developer. From my perspective, I estimate the goodness of an idea as inversely related to how good its originator thinks it is.

If your skills aren't good enough, there is only one way to improve them. Use them! Reach for the stars and try and develop the software. Even if nothing comes of it, you will have made your skills much better.

ContentLicense: CC BY-SA 2.5


问:
Connecting a native iOS app to backend and database
I have a good amount of experience working with objective-C and making iOS apps that work locally and with BaaS providers (Parse.com). However, I'd like to take my mobile development to the next level and I'd like tips on the order in which to do things and tips on which services/technologies to use.

So, I need a database, and a place to host my database. I've used Amazon AWS for some things, and I can easily set up a mySQL DB on an EC2 instance there. Alternatively, I've heard that GAE is very useful.

I don't really know if I have to write any back-end code. It seems to me that objective-C can take the place of my back-end code. Is that secure? Should I be making an entire service that is simply called from the iPhone?

So, I know that it's a loaded question, and it may require a few different opinions to really round out a good answer. Sorry about that. But, assuming that I am proficient enough with Obj-C to make anything happen client side, and that I'm sentient enough to learn other languages that I might not know and follow tutorials and examples online - What are the steps (and the best technologies/services at each step) to making a native iOS app that does not use a BaaS provider like Parse.com or Stackmob.com. Thanks!

答:
What's the reason to store data remote when it's just a one client offline app?

But to answer your question (not sure if I understand it correctly):

In most cases you gonna build a layer (e.g. a webservice) between your mobile app and your database. The webservice is responsible for data manipulation (access the database and offers through an API just these methods/data which are absolutely needed, handles multi user concurrent database access and so on), provides security mechanisms (authentication, authorization), abstraction of concerns, implements business rules/logic, ...

And I'm sure you will write back-end code. Depending on you project you might have the requirement to provide access to other developers...at this point at least you must have an API for regulated access!


问:
Is this an example of 'over engineered' or a good practice?
The code I've inherited has a design that I'm not familiar with (I'm still new to the world of programming).

It is a .net project and there are 3 classes in question here.

```<code>public Class1
{
    public void DoSomething()
    {
        Class2 class2 = new Class2();
        string myValue = class2.GetSomeValuePlease();

       //why would I not do class2.MyClass3.GetActualValue();
    }
}

public Class2
{
    public Class3 MyClass3 = new Class3();
    public string GetSomeValuePlease()
    {
        return this.MyClass3.TheActualValue();
    }
}

public Class3
{
    public string TheActualValue()
    {
        return "This is the value";
    }
}
</code>```

As you can see, all 3 classes are public. I don't understand why, using the example above, I would use Class2 at all? I could understand if within the GetSomeValuePlease() method there was some logic which affected Class2, but there isn't.

Normally, I'd just go ahead and remove the Class2 method (GetSomeValuePlease) and call Class3 method (GetActualValue) direct from Class1, but, the developer I took over (who is not contactable) is wiser and more experienced than I. I have a feeling this is just over engineering and this is just extra code / extra maintenance.

Does any one have experience in designing this way that could explain the thought process or implications of having this "middle class" vs going direct?

答:
It depends. The good news is that if you understand the refactoring, you can reverse your decision later.

The advantage of the code as written is that you have more flexibility to change the internal structure of Class2 or change Class3 without affecting Class1.

The disadvantage is that every time you want to add a feature to Class3 that is used by Class1, you have to add a delegate method to Class2.

I suggest that you trust your instincts. You can use Remove the Middle Man to have the Class1 call Class3 directly.

If later you decide you should go back to the original design, you can use Hide Delegate.

I recommend the book Refactoring: Improving the Design of Existing Code by Martin Fowler.


答:
This is the application of the "Law of Demeter"  (which is not so much a law, but a good guide)

http://en.wikipedia.org/wiki/Law_of_Demeter

The basic idea is not to reach through objects to get access to other objects as that increases your coupling with an eco system of objects, meaning, changes are likely to ripple through entire systems.

However, I have seen people go too far with this and end up building facades to other objects into objects that have their own responsibility.

Most often if you find you want to apply "LoD" and find you are doing this kind of delegating / facade / Bridge type stuff, start having a good think about whether your design is right, because quite often a slight adjustment to the design / responsibilities will untangle the need to reach through one object to get to other objects.

Title: Is this an example of 'over engineered' or a good practice?

Body:
The code I've inherited has a design that I'm not familiar with (I'm still new to the world of programming).

It is a .net project and there are 3 classes in question here.

```<code>public Class1
{
    public void DoSomething()
    {
        Class2 class2 = new Class2();
        string myValue = class2.GetSomeValuePlease();

       //why would I not do class2.MyClass3.GetActualValue();
    }
}

public Class2
{
    public Class3 MyClass3 = new Class3();
    public string GetSomeValuePlease()
    {
        return this.MyClass3.TheActualValue();
    }
}

public Class3
{
    public string TheActualValue()
    {
        return "This is the value";
    }
}
</code>```

As you can see, all 3 classes are public. I don't understand why, using the example above, I would use Class2 at all? I could understand if within the GetSomeValuePlease() method there was some logic which affected Class2, but there isn't.

Normally, I'd just go ahead and remove the Class2 method (GetSomeValuePlease) and call Class3 method (GetActualValue) direct from Class1, but, the developer I took over (who is not contactable) is wiser and more experienced than I. I have a feeling this is just over engineering and this is just extra code / extra maintenance.

Does any one have experience in designing this way that could explain the thought process or implications of having this "middle class" vs going direct?


答:
The biggest argument against multiple inheritance is that some useful abilities can be provided, and some useful axioms can hold, in a framework which severely restricts it(*), but cannot cannot be provided and/or hold without such restrictions.  Among them:

The ability to have multiple separately-compiled modules include classes which inherit from other module's classes, and recompile a module containing a base class without having to recompile every module that inherits from that base class.

The ability for a type to inherit a member implementation from a parent class without the derived type having to re-implement it

The axiom that any object instance may be upcast or downcast directly to itself or any of its base types, and such upcasts and downcasts, in any combination or sequence, are always identity-preserving

The axiom that if a derived class overrides and chains to a base-class member, the base member will be invoked directly by the chaining code, and will not be invoked anywhere else.

(*) Typically by requiring that types supporting multiple inheritance be declared as "interfaces" rather than classes, and not allowing interfaces to do everything normal classes can do.

If one wishes to allow generalized multiple inheritance, something else must give way.  If X and Y both inherit from B, they both override the same member M and chain to the base implementation, and if D inherits from X and Y but does not override M, then given an instance q of type D, what should ((B)q).M() do?  Disallowing such a cast would violate the axiom that says any object can be upcast to any base type, but any possible behavior of the cast and member invocation would violate the axiom regarding method chaining.  One could require that classes only be loaded in combination with the particular version of a base class they were compiled against, but that is often awkward.  Having the runtime refuse to load any type in which any ancestor can be reached by more than one route might be workable, but would greatly limit the usefulness of multiple inheritance.  Allowing shared inheritance paths only when no conflicts exist would create situations where an old version of X would be compatible with an old or new Y, and an old Y would be compatible with an old or new X, but the new X and new Y would be compatible, even if neither did anything which in and of itself should be expected to be a breaking change.

Some languages and frameworks do allow multiple inheritance, on the theory that what's gained from MI is more important than what must be given up to allow it.  The costs of MI are significant, however, and for many cases interfaces provide 90% of the benefits of MI at a small fraction of the cost.


问:
Arrays vs Objects in view template
I am wondering, in view templates, what would contribute to me choosing between using arrays or objects for getting things printed out in arrays

{{$user->zip_code}} vs {{$user['zip_code']}}

I'm working in blade templates in Laravel/PHP fwiw.

My feeling is that it makes sense to use objects: we can use methods if we need to to display/format data, it looks a lot cleaner in the views, and bc of how PHP works fails gracefully if the item isn't set (an unset array value will puke, so you either need to make sure all possible properties are present but false, or do a {{(isset($user['zip_code'])) ? $user['zip_code'] : ''}} for everything you use in a view.

However, I have encountered some contrasting opinions like:
the less the view knows about the layers below it, the better. As such, "flat" values (arrays) are better to use in the view.
We should not trust the view not to explode if a value is not set, that should be handled in the controller.

Because our object properties are not encoded in the models in this system, we can't rely on each object always having the same info in a model level.

Wondering if there are other factors at play here. Orr.. Does it not matter

答:
Use objects.

Objects are most always better.  I say most always because people will always have their preferences/opinions/skillset (when they takeover or further change your codebase).  In particular, whether it's Twig, Blade, etc... it is relatively irrelevant.

Er, I digress into philosophy...

Main reason is if you rename 'zip_code' to 'ZipCode' (or something similar) then your template variables will BREAK!  However, if you're using an object based implementation [ie, a real PHP Model or Object representation of $user] then the 'magic' __get will be implemented looking at your object's parameter(s), OR you can implement a getZipCode() method that would return was is needed.

Point being is it'll be more robust if you use objects.

Title: Arrays vs Objects in view template


问:
Working with CPU cycles in Gameboy Advance
I am working on an GBA emulator and stuck at implementing CPU cycles.
I just know the basic knowledge about it, each instruction of ARM and
THUMB mode as each different set of cycles for each instructions.
Currently I am simply saying every ARM instructions cost 4 cycles and
THUMB instructions cost 2 cycles. But how do you implement it like the
CPU documentation says? Does instruction cycles vary depending on which
section of the memory it's currently accessing to?
http://nocash.emubase.de/gbatek.htm#cpuinstructioncycletimes
According to the above specification, it says different memory areas have
different waitstates but I don't know what it exactly mean. Furthermore,
what are Non-sequential cycle, Sequential cycle, Internal Cycle,  Coprocessor Cycle for?
I saw in some GBA source code that they are using PC to figure out how many cycles each
instruction takes to complete, but how are they doing it?</p>

答:
This is only a partial response, so it may be disallowed:

Currently I am simply saying every ARM instructions cost 4 cycles and
  THUMB instructions cost 2 cycles.

Actually, if I'm remembering ARM correctly, what's actually happening is that, in a single memory cycle, you can either fetch a single 32-bit ARM instruction, or two 16-bit THUMB instructions.  Execution time is, of course, instruction-dependent.

Does instruction cycles vary depending on
  which section of the memory it's currently accessing to?
  http://nocash.emubase.de/gbatek.htm#cpuinstructioncycletimes According
  to the above specification, it says different memory areas have
  different waitstates but I don't know what it exactly mean.

Different regions of memory may have more data clients than just the CPU.  This is particularly true in graphics/video memory where pixels need to be pulled out of RAM to send off to the display.  Unless you use faster (read: more expensive) memory, the CPU and graphics hardware will have to take turns accessing RAM.  Thus, depending on how many other RAM clients there are, it may take several cycles before the CPU's turn at RAM arrives.

It may not even be this noble -- the manufacturer may have simply decided that they could get away with slower (read: cheaper) RAM for most of program and data space, and used a smaller block of fast memory only for those things that absolutely needed it.

Furthermore, what are Non-sequential cycle, Sequential cycle, Internal
  Cycle, Coprocessor Cycle for?

Sequential versus non-sequential refers to reading memory locations in order versus out-of-order.  RAM is arranged as a two-dimensional array of memory cells indexed by row and column address.  If you access memory locations in ascending address order (e.g. 0, 1, 2, 3, 4, 5, etc.), then all you need to change (most of the time) is the column address, and each successive read can be satisfied more quickly than if you accessed addresses non-sequentially.  Judging from the doc you linked to, it looks like you get a CAS increment for free, but a full RAS+CAS costs an extra cycle.

Internal Cycle means the CPU is going, "Wow, this is complicated; gimme some extra time to figure this out."  (The MUL instructions are sharp examples of this.)

Coprocessor Cycle refers to the time required to talk to an ARM coprocessor.  I don't know what, if any, ARM coprocessors are in the GBA.

As for implementation: That doesn't lend itself to a single answer.  If it were me, I'd model RAM access times independently from instruction execution times.  When the CPU reads/writes memory, compare the memory address accessed with the previous memory address the CPU accessed.  If they're adjacent (M(current) == M(previous) + 4), then it's free; otherwise add a one-cycle penalty.  Then add the delays imposed by the memory region you're accessing.


答:
If you don't start, it will never be done. Best case scenario for choice B? You'll find many "advanced" programmers who are fully on board, who would like to create a domain name for the project, logos, feature lists for version 2.0, ... everything but actual coding. They'll respect the concept so much, they won't want to blemish it with anything that might go wrong.

Actions are what count. If you have a really great idea, you'll be on your own for a while. You may have troubles communicating it, because you've internalized it so much, and it will seem that people are incapable of seeing your vision. They'll comment on trivial matters and miss the big picture. Until you have something concrete, that's how it's going to be. Only in working with it for a while will you be able to get your perfect elevator pitch for it.

At this point, since you explicitly mentioned you were looking for sage words: Have a growth mindset. Programming advanced things is how you become an advanced programmer. Where you are now doesn't matter. What matters is that you reach a new personal best.

Go with A. And good luck!

Title: Should I start a project I am hoping to recruit others to?

Body:
I have an idea for a program that I think is a good one (Don't we all?).  I am an amateur programmer and would like to recruit some more advanced programmers onto the project since there are some aspects that I am not skilled enough to do myself.  Is it better to

a) Develop the software on my own as much as I can, even though it will be amateurish, and then show a demo to potential recruits

or

b) Try and recruit some more advanced programmers and seek their advice and guidance before I get started so that it is done correctly from the beginning?

I would especially love it if someone has any experience of being in a similar position, but sage speculation is welcome too.


问:
How to explain to my manager the importance of separation of concerns?
I'm an extremely novice web programmer working at a 2 person shop building websites, and we're in the process of writing a simple website template system in PHP from scratch. My manager is entirely self taught. He has been insisting that we put our HTML directly quoted in variables, mixing our back end code with the front end stuff.

```<code>$foo = "<html>
        <body>
            <div class=\"bar\">" . $bar . "</div>
        </body>
        </html>";

echo $foo;
</code>```

He claims that it is easier to work with this way. I insisted that we should at least use PHP tags in our HTML, rather than the HTML in the PHP.

```<code><html>
<body>
    <div class="bar"><?php echo $bar; ?></div>
</body>
</html>
</code>```

I feel like this is a real pain in the ass to read and it just looks like a mess. I think it would be a lot easier to separate the logic from the presentation, but he is certain that his way is best. How can I explain the importance of this so that he will understand? I can't put it into words, exactly.

EDIT: Think you guys could leave a comment when you're down voting me? I have no idea how to fix my question if you just down vote it and leave without suggesting improvements.

答:
I would approach this as follows: you have two separate concerns, the view and the application logic.  Simply remind him that, since view code and application code are all mixed in together, changes to the view could (hint: at some point they will) break the application logic.  Similarly, changes to the application logic could mess up the view.  That is probably the best rationale for separation of concerns -- code isolation.

Another possible argument is that, at some point, the web applications you are developing may need additional front-ends (think customized mobile site, REST/XML interface, etc.)  With application logic and view code all mergled (merged and mangled) together, adding additional view technologies becomes a nightmare.

Finally, how does he intend to test the application code separate from the view (or does he see the need for unit testing)?  With cleanly separated code, testing becomes much easier.  That is all I can think of off the top of my head.  Hope everything works out for you.


问:
Do you believe it's a good idea for Software Engineers to have to work as Quality Assurance Engineers for some period of time?
I believe it is.  Why?

I've encountered many Software Engineers who believe they are somehow superior to QA engineers.  I think it may help quench this belief if they do the job of a QA engineer for some time, and realize that it is a unique and valuable skill-set of its own.

The better a Software Engineer is at testing their own programs, the less cost in time their code incurs when making its way through the rest of the software development life-cycle.

The more time a Software Engineer spends thinking about how a program can break, the more often they are to consider these cases as they are developing them, thus reducing bugs in the end product.

A Software Engineer's definition of "complete" is always interesting...if they have spent time as a QA engineer maybe this definition will more closely match the designer of the software's.

Note I make above suggestion with a small time-frame in mind as I am aware having someone work in a position that is not the position they are hired for is definitely a recipe for losing that developer.

What do you all think?

答:
"...have to work as QA engineers..."? You make it sound adversarial or punishment.

I am a software developer. I consider it part of my job to be a QA engineer also, even though we have a QA department. It's my job to deliver software that accomplishes certain things, and, to do that I have to write unit tests and make sure the software passes them.

I am in partnership with our QA department. My goal is to make their jobs easier, just as their job is to help me meet my goal of delivering software that does what it should, thereby making my life easier. I consider them my second set of eyes and somewhat of a safety net, just as I do my unit tests.

I choose to develop software, and want to develop software. If some manager came to me and told me I couldn't do that and had to do QA, I'd tell them they need to find a new software developer AND a QA person because I won't be working there. I am anal as can be with my code but the creative process and programming puzzle/challenge is extremely important to me. I'd rather go back to driving fork lifts if I can't write code because being in a corporate environment without the perk of being creative and being challenged the way I am would be absolute hell to me.

In general the options you present sound very adversarial and leave me wondering if you've had some really bad experiences with some terrible developers. In my mind, a developer must ALWAYS be aware of quality issues and testing and should be proud enough of their work that they don't consider it finished until it passes as rigorous tests in their unit testing as what the official QA department will use. If I had a peer, or was tech-lead on a team and had a developer who showed any "'tude" toward QA he'd find me hauling him off for an attitude correction. If both sides of the software-delivery coin can't cooperate and act as a team there is a real culture problem. I wouldn't want to work there and HR, along with upper-management, would need to be clued in.


答:
I would argue that there aren't any real problems with MI in the right language. The key is to allow diamond structures, but require that subtypes provide their own override, instead of the compiler picking one of the implementations based on some rule.

I do this in Guava, a language I'm working on. One feature of Guava is that we can invoke a specific supertype's implementation of a method. So it's easy to indicate which supertype implementation should be "inherited", without any special syntax:

```<code>type Sequence[+A] {
  String toString() {
    return "[" + ... + "]";
  }
}

type Set[+A] {
  String toString() {
    return "{" + ... + "}";
  }
}

type OrderedSet[+A] extends Sequence[A], Set[A] {
  String toString() {
    // This is Guava's syntax for statically invoking instance methods
    return Set.toString(this);
  }
}
</code>```

If we didn't give OrderedSet its own toString, we would get a compilation error. No surprises.

I find MI to be particularly useful with collections. For example, I like to use a RandomlyEnumerableSequence type to avoid declaring getEnumerator for arrays, deques, and so forth:

```<code>type Enumerable[+A] {
  Source[A] getEnumerator();
}

type Sequence[+A] extends Enumerable[A] {
  A get(Int index);
}

type RandomlyEnumerableSequence[+A] extends Sequence[A] {
  Source[A] getEnumerator() {
    ...
  }
}

type DynamicArray[A] extends MutableStack[A],
                             RandomlyEnumerableSequence[A] {
  // No need to define getEnumerator.
}
</code>```

If we didn't have MI, we could write a RandomAccessEnumerator for several collections to use, but having to write a brief getEnumerator method still adds boilerplate.

Similarly, MI is useful for inheriting standard implementations of equals, hashCode and toString for collections.

Body:
I would argue that there aren't any real problems with MI in the right language. The key is to allow diamond structures, but require that subtypes provide their own override, instead of the compiler picking one of the implementations based on some rule.

I do this in Guava, a language I'm working on. One feature of Guava is that we can invoke a specific supertype's implementation of a method. So it's easy to indicate which supertype implementation should be "inherited", without any special syntax:

type Sequence[+A] {
  String toString() {
    return "[" + ... + "]";
  }
}

type Set[+A] {
  String toString() {
    return "{" + ... + "}";
  }
}

type OrderedSet[+A] extends Sequence[A], Set[A] {
  String toString() {
    // This is Guava's syntax for statically invoking instance methods
    return Set.toString(this);
  }
}

If we didn't give OrderedSet its own toString, we would get a compilation error. No surprises.

I find MI to be particularly useful with collections. For example, I like to use a RandomlyEnumerableSequence type to avoid declaring getEnumerator for arrays, deques, and so forth:

type Enumerable[+A] {
  Source[A] getEnumerator();
}

type Sequence[+A] extends Enumerable[A] {
  A get(Int index);
}

type RandomlyEnumerableSequence[+A] extends Sequence[A] {
  Source[A] getEnumerator() {
    ...
  }
}

type DynamicArray[A] extends MutableStack[A],
                             RandomlyEnumerableSequence[A] {
  // No need to define getEnumerator.
}

If we didn't have MI, we could write a RandomAccessEnumerator for several collections to use, but having to write a brief getEnumerator method still adds boilerplate.

Similarly, MI is useful for inheriting standard implementations of equals, hashCode and toString for collections.


答:
Nobody should start to undertake a large project. You start with a small trivial project,
  and you should never expect it to get large. If you do, you'll just overdesign and generally
  think it's more important than it is likely at that stage. Or worse - you might be scared
  away by the sheer size of the work you envision.
  So start small, and think about the details. Don't think about some big picture and fancy
  design. It if doesn't solve some fairly immediate need, it's almost certantly over designed.
  And don't expect people to jump in and help you. That's not how it works. You need to get
  something half way first, and only then others will say "hey, that almost works for me",
  and get involved in the project.

— Linus Torvalds

pretty much sums it...


问:
How to avoid dragging arguments from function to function
When I do my code layout, I like to start with a rather high level view, and then start to delegate actual computation to class or functions that have a bit more detail. Then in these classes of functions, I do the same, layer by layer, until I get to the bottom where I have to do the 'real' action.

Example:

```<code>def build_table():
    legs = get_legs()
    plate = get_plate()
    return put_together(legs, plate)

def get_legs():
    legs = []
    for i in [0,1,2,3]:
        legs.append(get_leg_from_warehouse())
    return legs

def get_plate():
    plate = get_plate_from_warehouse()
    return finish_plate(plate)

def put_together(legs, plate):
    table = Table()
    for i in [0,1,2,3]:
       table.mount(legs[i])
    table.mount(plate)
    return table

class Table:
    self.component = []
    def mount(self, item):
        self.component.append(item)
</code>```

In this way, I find it easy to think about the layout, and hide complexity. I mostly have short pieces of code that are easy to understand.

The downside of this is, that when I discover I need a piece of information available at the top of the stack further down, I pass arguments from function to function. In the above example, I might gather 'screws' at the top, and then keep passing them down to a function where they are actually drilled into the wood. This makes it feel that it is not so easy to modify the code, and I wondered what I could do about this. In this example the modified code would look like this:

```<code>def build_table():
    legs = get_legs()
    plate = get_plate()
    screws = get_screws()
    return put_together(legs, plate, screws)

def get_legs():
    legs = []
    for i in [0,1,2,3]:
        legs.append(get_leg_from_warehouse())
    return legs

def get_plate():
    plate = get_plate_from_warehouse()
    return finish_plate(plate)

def get_screws():
    drive_to_hardwarestore()
    screws = buy_screws()
    drive_home()
    return screws

def put_together(legs, plate, screws):
    table = Table()
    for i in [0,1,2,3]:
       table.mount(legs[i], screws)
    table.mount(plate, screws)
    return table

class Table:
    self.component = []
    def mount(self, item, screws):
        self.component.append((item, screws.pop()))
</code>```

So besides adding the code for getting screws, I had to modify 4 lines. This would increase linearly with the amount of layers.

How can I refactor?
On the other hand, how can I avoid this in the first place? Is my design process 'wrong'?

答:
So besides adding the code for getting screws, I had to modify 4 lines. This would increase linearly with the amount of layers.

I think this is a fallacy. When you add another kind of table part, you will still have only to change 4 lines of code in your "object construction layer". The layers above the "object construction" layer in your code will just work with "table" objects, unmodified, as long as they don't have to deal with the new kind of parts. You can pass that table object through an arbitrary number of layers and don't have to change anything. And when you find a part in your code where you have to access your screws, that code can just ask the "table object" for the screws.

Of course, when the object construction process itself gets more complicated, and you think you have "too much passing around" in there, you may consider to create a (table) factory class to encapsulate the constructions. That way, it is possible to create  "screws", "legs", and "plate" in one place, store them in member variables of the factory, and get them later in the "mount" function.

So as long as the construction process is simple, stick to your design, and if it gets more complicated, use factory classes.


问:
Entity framework and Eager loading and enterprise application with DDD aproach
We are trying to create an ASP.NET MVC 4 application using entity framework with domain driven development style pattern approach. As you can see in our part of domain layer, we have a complex design. We need to load entity with lazy as well as eager methods. Unfortunately we have big problem with these methods in entity framework.

As we understand, for eager loading in EF we have to use the Include method and give string of properties and properties of properties etc. (In Hibernate and java we could use annotation top of member to load eagerly and it was so much easier than this approach). But the horrible problem is that we have inheritance structures and heavy polymorphism, in these states we don’t have that’s string we should given to include because we don’t know which derived class of class is selected to understand which properties should include.

For example as you can see a result has a collection of items and then decides to add some group to this collection and each of those groups have some groups and fields (like the composition pattern). Now imagine we want to load a result is like the one talked above. When I want to write a string of given include I don’t know what items of this result are groups. Because we can’t predict these items are groups and so these groups have collection of items which should load.

```<code>this.Items = new List<Item>
            {
                new Group(
                    a,
                    new List<Item>
                    {
                        new Field(b),
                        new Field(c),
                        new Field(d),
</code>```

At last we have a critical question: is entity framework designed for Enterprise Applications with a complex domain and DDD approach? If not, how we follow the approach of Martin Fowler and Eric Evans in software engineering and enterprise application in C#?

答:
is entity framework designed for Enterprise Applications with a complex domain and DDD approach?

This might be only me, but I have yet to find an ORM that would allow you to create a clean DDD model and have it seamlessly mapped to relational data model. You always need some level of change to your DDD to support the ORM mapping. The lazy loading is one of them. Requirement for public properties or parameter-less constructors is another I noticed.

If not, how we follow the approach of Martin Fowler and Eric Evans in software engineering and enterprise application in C#?

I think that original idea of DDD was that there was persistence layer on top of DDD that was specifically tailored for that specific model. Quite often going as low as pure SQL. ORMs being generic frameworks don't have luxury of that specific way of mapping. Some, like nHibernate, get close simply because of their scale and amount of features. But I still think ORM mappers can't generally be used to map properly designed DDD to relational without changes to the DDD model.


问:
How to handle multiple licenses in your code
So let’s say I make a script/small app that has a ton of my own code, and only a small section of it is comprised of a utility from someone else (let’s say a simple operation like sending files to the trash, or sending a notification), which uses a license, like MIT.

Now, I want my script/app to be public domain (or MIT licensed, let’s take two examples).

How do I make the distinction for this in my code? How do I exactly explain “this part of the code is encumbered by this license, and this other part is my license”?

Every copy of it I distribute needs to include the license? That seems really idiotic/cumbersome, having to pass a dumb text file around.

Do I then have to include both files (theirs and mine)?

Number 3 is my biggest doubt, how do I reliably and clearly point each portion of the code to each specific license? I won’t go on a rant about this, but it is honestly the most stressful part of programming, to me, can’t we just happily share code amongst peers? In the examples above, none of those apps are “mission critical”, but they are nice additions, and not including them because of the confusion/limitations it causes is a real shame.

答:
In the example you give, the MIT license, it says

The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

So, if your software contains theirs then "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software".

That's all there is to it.

It's a good idea to put the licensed software in it's own directory, along with the license. Your main license files should highlight which parts are yours and which have another license.

The main directory where you hold documents such as the license (maybe the root directory of the project, or a Documentation directory), will contain files such as README.TXT or LICENSE.TXT. One of those should contain a section something like

This software includes third party open source software components: Foo, Bar, and Whatsit.
  Each of these software components have their own license. Please see ./Foo/License.txt,
  ./Bar/License.txt, and ./Whatsit/License.txt.

The main thing is to make clear that those parts have their own license, and since open source products nearly always require that the source must be available, provide a link to the source project, and/or the source itself.

Just make sure that anyone who looks can see that you are complying with the licenses.


问:
Visual Studio 2012 - Express vs Professional
I'm having trouble finding a feature comparison between Visual Studio 2012 Express Edition and the professional edition. I'm using the trial Professional version at the moment, but it'll run out soon, so I need to make a decision whether to purchase the full version.

Obviously, I can just try both initially and see if the Express edition is suitable, but the problem is that there are that many features in Visual Studio, there might be a really useful feature that was missing in the standard edition that I didn't even know existed! Or I didn't spot it was missing until later down the line. I could really do with a feature comparison list like the one for all non-Express editions here. It's a shame that page doesn't include the Express edition.

答:
Microsoft makes the Express version for students, learners and newcomers. It's very easy to get started and is specially designed for doing one thing. This thing make learning faster and confuse someone new to programming less than a professional.

As noted above.

Visual Studio Express web 13 only supported Web programming.

Visual studio Express Desktop only supported Desktop programming.

Of course, the Express version doesn't provide plugin support and many good features.

Visual studio Professional is a paid version for professionals. If you got into development then you need more features, so Visual Studio Professional is more reliable in that condition.

I hope this answer helps :)


问:
What are the advantages of Ceylon over Java?
Looking for the recent and powerful upcoming programming languages over net, I came across Ceylon. I dropped in at ceylon-lang.org and it says:

Ceylon is deeply influenced by Java. You see, we're fans of Java, but we know its limitations inside out. Ceylon keeps the best bits of Java but improves things that in our experience are annoying, tedious, frustrating, difficult to understand, or bugprone.

What are the advantages of Ceylon over Java?

答:
I think Ceylon is interesting in many ways. And maybe they are right in the way that you need to depart from Java in some ways if you want to leave some problems of Java behind you. Ceylon seems to have quite a few language features and I hope this does make the compiler slow as in Scala or even worse cause build times that don't scale with the code size (see Two years of Scala experience feedback). The pace of the Ceylon dev team is quite impressive. </p>

<p>Kotlin is still 0.6 and, judging from their development speed in the last year, I would say about a year away from 1.0. It does not have that many language features like Ceylon (but those important ones java is missing like traits and extension methods) and seems to be more some kind of Scala without the problems of it. I guess scalable build times won't be a problem with it. But Kotlin can only be a nicer Java like Groovy. It can't provide a way out of Java commodity programming with XML dependency, boilerplate code, byte code manipulation, etc. It is something like Java and Scala done right. Whether Kotlin or Ceylon will be able to make a difference remains to be seen. I think both attempts are worth the effort and I wish them both good luck. </p>

Body:
I think Ceylon is interesting in many ways. And maybe they are right in the way that you need to depart from Java in some ways if you want to leave some problems of Java behind you. Ceylon seems to have quite a few language features and I hope this does make the compiler slow as in Scala or even worse cause build times that don't scale with the code size (see Two years of Scala experience feedback). The pace of the Ceylon dev team is quite impressive.

Kotlin is still 0.6 and, judging from their development speed in the last year, I would say about a year away from 1.0. It does not have that many language features like Ceylon (but those important ones java is missing like traits and extension methods) and seems to be more some kind of Scala without the problems of it. I guess scalable build times won't be a problem with it. But Kotlin can only be a nicer Java like Groovy. It can't provide a way out of Java commodity programming with XML dependency, boilerplate code, byte code manipulation, etc. It is something like Java and Scala done right. Whether Kotlin or Ceylon will be able to make a difference remains to be seen. I think both attempts are worth the effort and I wish them both good luck.


问:
Where do we put "asking the world" code when we separate computation from side effects?
According to Command-Query Separation principle, as well as Thinking in Data and DDD with Clojure presentations one should separate side effects (modifying the world) from computations and decisions, so that it would be easier to understand and test both parts.

This leaves an unanswered question: where relatively to the boundary should we put "asking the world"? On the one hand, requesting data from external systems (like database, extental services' APIs etc) is not referentially transparent and thus should not sit together with pure computational and decision making code. On the other hand, it's problematic, or maybe impossible to tease them apart from computational part and pass it as an argument as because we may not know in advance which data we may need to request.

答:
You store the result in the class, this seems a bit strange at first, but does result in simpler code. e.g. no temporary variables in caller.</p>

```<code>class database_querier
    feature -- queries
        was_previous_query_ok : boolean is
            do
                Result = …
            end

        previous_query_result : string is
            requires
                was_previous_query_ok
            do
                Result = query_result
            end

    feature -- commands
        query_db (…) is
            do
                …
                query_result = bla
            end

    feature {none} --data
        query_result : string
</code>```

Body:
You store the result in the class, this seems a bit strange at first, but does result in simpler code. e.g. no temporary variables in caller.

class database_querier
    feature -- queries
        was_previous_query_ok : boolean is
            do
                Result = …
            end

        previous_query_result : string is
            requires
                was_previous_query_ok
            do
                Result = query_result
            end

    feature -- commands
        query_db (…) is
            do
                …
                query_result = bla
            end

    feature {none} --data
        query_result : string


问:
Where did Java go wrong on the client?
Not talking about the recent Java/Oracle debacle here, but something I've been wondering recently.

When I first started programming, Java was the big thing client-side, however these days you hardly ever see a Java applet whereas Flash and Javascript are ubiquitous.

Where did Java go wrong? Did Sun decide to concentrate on the server-side and let client-side stagnate? How did Flash become dominant over Java? Flashy (no pun intended) graphics? Marketing?

Never having been a Java developer, I've not followed this closely so I'm interested to hear your thoughts.

答:
I believe streaming video was the "killer app" for Flash. Although video had been tried before in Java applets, the frame rate wasn't very high and it required users to install the relatively heavyweight JRE.

Along came Flash with its small install size and (eventually) high video frame rate. It helped that browser vendors started including Flash as part of the default browser installation.

Java is still hindered by a large installation size and slow start times compared to Flash.

Title: Where did Java go wrong on the client?


问:
Making an algorithm more efficient
I have a question about the efficiency of an algorithm:

You have a list of x,y points

Now I want to get all the points that are up to 5 units away from a reference x,y point

How do you calculate it in the most efficient way?

I just go over each point and calculate distance, and if that distance is less than 5, I add it to the answer

If you know how this algorithm is called - I'd be happy if you post that too.

答:
While you cannot avoid having to check every point, there are techniques you can use to check quickly or check only once.

For example, most points you can tell if they are too far away without calculating the exact distance.  For example, if I have a point whose x component is 100 away from the point of reference, you don't have to calculate distance.  You already know that the point is too far away.  Likewise if the x and y deltas are less than 5*2*sqrt(2) away from the point of reference, you know they are close enough.  See the diagram below for a visual example:

If P is your point of origin and the circle represents the farthest away that a point can be from point P (in your case radius of 5 units), then A and C represents places where points are definitely out or definitely in.  Therefore, you can optimize your algorithm by checking x and y deltas.  Only points which lie in the gray area B should have their distance calculated because you cannot know without performing a more sophisticated calculation.

Also, it would not hurt to sort your points by distance to P.  If you have to perform this calculation often, you could optimize calculation by sorting once, then finding the farthest point within 5 units from P.  Unless point positions change, you know that all points after that point must be closer.

I hope that helps!

Title: Making an algorithm more efficient


问:
SQL-99 specification, is it specified to first order the result and limit it afterwards?
If I wrote this in MySQL

```<code>SELECT * FROM foo ORDER BY bar LIMIT 1
</code>```

it would first order the result and limit it afterwards. I always get the lowest bar.

I wonder if this is specified like this in SQL-standards and how to check that?

All I found are some BNF's which do not explain how something should work, but only what syntax is valid.

答:
SQL 99 has no LIMIT. That is an extension in MySQL (and few other databases) initially created by PHP's founder Rasmus Lerdorf.

SQL 2003 added support for a comparable OFFSET sytnax of this form:

```<code>SELECT ... [ ORDER BY ... ]
   OFFSET num {ROW|ROWS} FETCH {FIRST|NEXT} [num] {ROW|ROWS} ONLY
</code>```

Not sure any RDMBS supports that, yet.

For checking such features you can buy the standard from ISO. But as most databases implement things slightly of standard. In practical terms you will do better by checking the manuals of the systems you want to support and proper testing of your application.

Body:
SQL 99 has no LIMIT. That is an extension in MySQL (and few other databases) initially created by PHP's founder Rasmus Lerdorf.

SQL 2003 added support for a comparable OFFSET sytnax of this form:

SELECT ... [ ORDER BY ... ]
   OFFSET num {ROW|ROWS} FETCH {FIRST|NEXT} [num] {ROW|ROWS} ONLY

Not sure any RDMBS supports that, yet.

For checking such features you can buy the standard from ISO. But as most databases implement things slightly of standard. In practical terms you will do better by checking the manuals of the systems you want to support and proper testing of your application.


问:
Managing codebase for basic and pro edition of a project
I have a project which will have basic and professional edition. The professional edition will have all the features of the basic edition. I am using git to manage the project's codebase.

I consider that I will fork repo of the basic edition after I completed it. Then, I will start to code the professional edition on the forked repo.

My problem is that if there would be a bug in the basic edition in the future, I don't want to fix the bug in the basic edition and professional edition twice. How to handle this situation?

答:
Well, git is very nice in that it allows you to have multiple remotes.

For example, you can have this in your .git/config:

```<code>[remote "basic"]
    url = git@github.com:haitaka/project-basic.git
    fetch = +refs/heads/*:refs/remotes/origin/*

[remote "pro"]
    url = git@github.com:haitaka/project-pro.git
    fetch = +refs/heads/*:refs/remotes/origin/*
</code>```

This allows you, while being in your pro project, to do this:

```<code>git pull basic master
</code>```

And it will merge the changes from the basic project into the pro project.

Of course, this will only work if the pro features are completely separated from the basic features, codewise.

Body:
Well, git is very nice in that it allows you to have multiple remotes.

For example, you can have this in your .git/config:

[remote "basic"]
    url = git@github.com:haitaka/project-basic.git
    fetch = +refs/heads/*:refs/remotes/origin/*

[remote "pro"]
    url = git@github.com:haitaka/project-pro.git
    fetch = +refs/heads/*:refs/remotes/origin/*

This allows you, while being in your pro project, to do this:

git pull basic master

And it will merge the changes from the basic project into the pro project.

Of course, this will only work if the pro features are completely separated from the basic features, codewise.


答: This is a common problem, and there's exactly one known optimization for the one-shot case: check if the distance squared is smaller than 25. This saves you an expensive sqrt call per point. Squaring and adding coordinates is almost free, in comparison to the time it takes to retrieve the data from memory.

Title: Making an algorithm more efficient

Body:
I have a question about the efficiency of an algorithm:

You have a list of x,y points

Now I want to get all the points that are up to 5 units away from a reference x,y point

How do you calculate it in the most efficient way?

I just go over each point and calculate distance, and if that distance is less than 5, I add it to the answer

If you know how this algorithm is called - I'd be happy if you post that too.


问:
How does this normalized example work?
I had the following DB schema:

```<code>Customer   Car     Rental
-------   ----     ------
Name      Name     Car_ID
ID        ID       Customer_ID
                   Date
</code>```

This is said to be non normalized as the date can repeat (multiple customers can rent a car at the same day). So the teacher said it should be like:

```<code>Customer  Car Date
------    --- ----
</code>```

and linked with foreign keys.

Well I do not get that - how can I then simply enter that "John rented a BMW on 2/3/2013"?

答:
You would enter that fact by first creating (or looking up) a record in Date to represent Mar 2, 2013, then create a new record in Rental with three foreign keys. (You still need the table Rental, otherwise you can't represent arbitrary re-rentings of a customer or a car - or on the same date.)

However, that is surely unnecessary. A date is one scalar piece of information - the fact that it's formatted XX/YY/ZZZZ or MMM DD, YYYY doesn't affect its identity, and formatting rules shouldn't be imposed by the storing the display form in databases anyway. My opinion is that storing dates as a scalar field in another table (here: Rental) is perfectly normal - a date is effectively a day number, i.e. no worse than any other foreign key you'd use.

Title: How does this normalized example work?


答:
I would not fork the pro edition: this would be almost like saying that it is a related, but different, project. It is not so: it's a fuller version, and it shares so much of the code that you rightly fear that you will have to fix a bug twice. So, don't do it and change your idea. You can implement a pro edition in different ways: distribute the full version and disable some feature in the basic version, adopt a modular solution where the pro edition has "more", or more powerful, plugins/modules...

So you share a core base and all the test, the bugfixes, the documentation and your investments in terms of time and resources will be useful for your project as a whole.

Title: Managing codebase for basic and pro edition of a project

Body:
I have a project which will have basic and professional edition. The professional edition will have all the features of the basic edition. I am using git to manage the project's codebase.

I consider that I will fork repo of the basic edition after I completed it. Then, I will start to code the professional edition on the forked repo.

My problem is that if there would be a bug in the basic edition in the future, I don't want to fix the bug in the basic edition and professional edition twice. How to handle this situation?


问:
Should I continue learning a language if in the meanwhile I became interested in another language/platform?
I started learning Java a couple of months ago. I also wanted to become more exposed to linux so I installed ubuntu and started working with Java since then. In the meanwhile however I became more interested in C# and in learning the Windows platform. At this point I'm asking myself if I should stop learning Java and move to the .NET world. I don't hate or dislike Java by the way, I am just more curious about windows/.NET at this point in time. </p>

<p>My question is, should I remain with Java or go with C#/.NET? What is your advice?  </p>

答:
At any point in my career I am learning two or three languages at the same time. It's fine to have a couple pots on the stove because you'll get bored or run into a problem that blocks you for a while with one so you temporarily switch to another.

Think of it this way: corporations/potential employers don't care as much about whether you are a total expert in a particular language as they do whether you are flexible and can turn out good code in any language they throw you at.

Having a good understanding of constructs and being able to apply them in multiple languages beats knowing esoterica about one language.

OwnerDisplayName: UML


问:
What's up with the Class::get(id) idiom in PHP
I am a new PHP developer (coming from .NET). The experienced php dev that I work with said that calling a static get method on a PHP class with an ID as a parameter is common in PHP.

Is there a name for this idiom? Is there a reason why developers do this? Can someone point to a link to an example class?

I would like to understand more of what he is saying. He is talking about code like this I think, to pull car #1 from the database:

```<code>$car = Car::get(1)
</code>```

答:
It's called the Singleton pattern and it's generally a bad design practice.

I'm assuming when you call Car::get(1) on the data model for Car it uses a singleton reference for the data source, queries the database and returns the record.

This is bad design.

Singletons hide the dependencies of the data model in the source code. The get() method is made static to avoid passing around an object reference. This creates fractures in the connection between business logic and data models.

It's just a really bad thing to do if this is how you're accessing your data.

It violates the Single Responsibility Principle because your models handle their own creation.

It creates tightly coupled code that is difficult to maintain.

It makes it very difficult to unit test.

The data models state is changed by multiple points in the source code outside the scope of the current caller.

The data models carry state changes into other business rules.

I could go on and on...