问:
How to Avoid Fragile Unit Tests?
We have written close to 3,000 tests -- data has been hard coded, very little reuse of code. This methodology has began to bite us. As the system changes we find ourselves spending more time fixing broken tests. We have unit, integration and functional tests.

What I'm looking for is a definitive way to write manageable and maintainable tests.

Frameworks

FakeItEasy

nUnit

AutoFixture

答:
I've had this problem as well. My improved approach has been as follows:

Don't write unit tests unless they're the only good way to test something.

I am fully prepared to admit that unit tests have the lowest cost of diagnosis and time-to-fix. This makes them a valuable tool. The problem is, with the obvious your-mileage-may-vary, that unit tests are often too petty to merit the cost of maintaining the code mass. I wrote an example at the bottom, have a look.

Use assertions wherever they are equivalent to the unit test for that component. Assertions have the nice property that they are always verified throughout any debug build. So instead of testing the "Employee" class constraints in a separate unit of tests, you're effectively testing the Employee class through every test case in the system. Assertions also have the nice property that they do not increase the code mass as much as unit tests (which eventually require scaffolding/mocking/whatever).

Before someone kills me: production builds should not crash on assertions. Instead, they should log at the "Error" level.

As a caution to someone who hasn't thought about it yet, do not assert anything on user or network input. It is a huge mistake™.

In my latest code bases, I've been judiciously removing unit tests wherever I see an obvious opportunity for assertions. This has significantly lowered the cost of maintenance overall and has made me a much happier person.

Prefer system/integration tests, implementing them for all of your primary flows and user experiences. Corner-cases probably do not need to be here. A system test verifies behavior at the user-end by running all components. Because of that, a system test is necessarily slower, so write the ones that matter (no more, no less) and you will catch the most important problems. System tests have very low maintenance overhead.

It's key to remember that, since you're using assertions, each system test will run a couple hundred "unit tests" at the same time. You're also rather assured that the most important ones get run multiple times.

Write strong APIs that can be tested functionally. Functional tests are awkward and (let's face it) kind of meaningless if your API makes it too hard to verify functioning components on their own. Good API design a) makes testing steps straightforward and b) begets clear and valuable assertions.

Functional testing is the hardest thing to get right, especially when you have components communicating one-to-many or (even worse, oh god) many-to-many across process barriers. The more inputs and outputs attached to a single component, the harder functional testing is, because you have to isolate one of them to really test its functionality.

On the issue of "don't write unit tests," I will present an example:

```<code>TEST(exception_thrown_on_null)
{
    InternalDataStructureType sink;
    ASSERT_THROWS(sink.consumeFrom(NULL), std::logic_error);
    try {
        sink.consumeFrom(NULL);
    } catch (const std::logic_error& e) {
        ASSERT(e.what() == "You must not pass NULL as a parameter!");
    }
}
</code>```

The writer of this test has added seven lines that do not contribute at all to the verification of the final product. The user should never see this happening, either because a) nobody should ever be passing NULL there (so write an assertion, then) or b) the NULL case should cause some different behavior. If the case is (b), write a test that actually verifies that behavior.

My philosophy has become that we should not test implementation artifacts. We should only test anything that can be considered an actual output. Otherwise, there's no way to avoid writing twice the basic mass of code between the unit tests (which force a particular implementation) and the implementation itself.

It is important to note, here, that there are good candidates for unit tests. In fact, there are even several situations where a unit test is the only adequate means by which to verify something and in which it is of high value to write and maintain those tests. Of the top of my head, this list includes nontrivial algorithms, exposed data containers in an API, and highly-optimized code that appears "complicated" (a.k.a. "the next guy will probably screw it up.").

My specific advice to you, then: Start deleting unit tests judiciously as they break, asking yourself the question, "is this an output, or am I wasting code?" You will probably succeed in reducing the number of things that are wasting your time.

OwnerDisplayName: Chuck Conway

Title: How to Avoid Fragile Unit Tests?

Body:
I've had this problem as well. My improved approach has been as follows:

Don't write unit tests unless they're the only good way to test something.

I am fully prepared to admit that unit tests have the lowest cost of diagnosis and time-to-fix. This makes them a valuable tool. The problem is, with the obvious your-mileage-may-vary, that unit tests are often too petty to merit the cost of maintaining the code mass. I wrote an example at the bottom, have a look.

Use assertions wherever they are equivalent to the unit test for that component. Assertions have the nice property that they are always verified throughout any debug build. So instead of testing the "Employee" class constraints in a separate unit of tests, you're effectively testing the Employee class through every test case in the system. Assertions also have the nice property that they do not increase the code mass as much as unit tests (which eventually require scaffolding/mocking/whatever).

Before someone kills me: production builds should not crash on assertions. Instead, they should log at the "Error" level.

As a caution to someone who hasn't thought about it yet, do not assert anything on user or network input. It is a huge mistake™.

In my latest code bases, I've been judiciously removing unit tests wherever I see an obvious opportunity for assertions. This has significantly lowered the cost of maintenance overall and has made me a much happier person.

Prefer system/integration tests, implementing them for all of your primary flows and user experiences. Corner-cases probably do not need to be here. A system test verifies behavior at the user-end by running all components. Because of that, a system test is necessarily slower, so write the ones that matter (no more, no less) and you will catch the most important problems. System tests have very low maintenance overhead.

It's key to remember that, since you're using assertions, each system test will run a couple hundred "unit tests" at the same time. You're also rather assured that the most important ones get run multiple times.

Write strong APIs that can be tested functionally. Functional tests are awkward and (let's face it) kind of meaningless if your API makes it too hard to verify functioning components on their own. Good API design a) makes testing steps straightforward and b) begets clear and valuable assertions.

Functional testing is the hardest thing to get right, especially when you have components communicating one-to-many or (even worse, oh god) many-to-many across process barriers. The more inputs and outputs attached to a single component, the harder functional testing is, because you have to isolate one of them to really test its functionality.

On the issue of "don't write unit tests," I will present an example:

TEST(exception_thrown_on_null)
{
    InternalDataStructureType sink;
    ASSERT_THROWS(sink.consumeFrom(NULL), std::logic_error);
    try {
        sink.consumeFrom(NULL);
    } catch (const std::logic_error& e) {
        ASSERT(e.what() == "You must not pass NULL as a parameter!");
    }
}

The writer of this test has added seven lines that do not contribute at all to the verification of the final product. The user should never see this happening, either because a) nobody should ever be passing NULL there (so write an assertion, then) or b) the NULL case should cause some different behavior. If the case is (b), write a test that actually verifies that behavior.

My philosophy has become that we should not test implementation artifacts. We should only test anything that can be considered an actual output. Otherwise, there's no way to avoid writing twice the basic mass of code between the unit tests (which force a particular implementation) and the implementation itself.

It is important to note, here, that there are good candidates for unit tests. In fact, there are even several situations where a unit test is the only adequate means by which to verify something and in which it is of high value to write and maintain those tests. Of the top of my head, this list includes nontrivial algorithms, exposed data containers in an API, and highly-optimized code that appears "complicated" (a.k.a. "the next guy will probably screw it up.").

My specific advice to you, then: Start deleting unit tests judiciously as they break, asking yourself the question, "is this an output, or am I wasting code?" You will probably succeed in reducing the number of things that are wasting your time.


问:
How is fundamental mathematics efficiently evaluated by programming languages?
As I get more and more involved with the theory behind programming, I find myself fascinated and dumbfounded by seemingly simple things..
I realize that my understanding of the majority of fundamental processes is justified through circular logic

Q: How does this work?

A: Because it does!

I hate this realization! I love knowledge, and on top of that I love learning, which leads me to my question (albeit it's a broad one).

Question:

How are fundamental mathematical operators assessed with programming languages?

How have current methods been improved?

Example

```<code>var = 5 * 5;
</code>```

My interpretation:

```<code>$num1 = 5; $num2 = 5; $num3 = 0;
while ($num2 > 0) {
    $num3 = $num3 + $num1;
    $num2 = $num2 - 1;
}
echo $num3;
</code>```

This seems to be highly inefficient. With Higher factors, this method is very slow while the standard built in method is instantanious. How would you simulate multiplication without iterating addition?

```<code>var = 5 / 5;
</code>```

How is this even done? I can't think of a way to literally split it 5 into 5 equal parts.

```<code>var = 5 ^ 5;
</code>```

Iterations of iterations of addition?
My interpretation:

```<code>$base = 5;
$mod = 5;
$num1 = $base;
while ($mod > 1) {

    $num2 = 5; $num3 = 0;
    while ($num2 > 0) {
        $num3 = $num3 + $num1;
        $num2 = $num2 - 1;
    }
    $num1 = $num3;
    $mod -=1;
}
echo $num3;
</code>```

Again, this is EXTREMELY inefficient, yet I can't think of another way to do this.
This same question extends to all mathematical related functions that are handled automagically.

答:
To really understand how arithmetic works inside a computer you need to have programmed in assembly language. Preferably one with a small word size and without multiplication and division instructions. Something like the 6502.

On the 6502, virtually all arithmetic is done in a register called the Accumulator. (A register is a special memory location inside the processor that can be accessed quickly.) So to add two numbers, you load the first number into the Accumulator, then add the second number to it.

But that's oversimplifying. Because the 6502 is an 8-bit processor, it can handle numbers only from 0 to 255. Most of the time you will want to be able to work with larger numbers. You have to add these in chunks, 8 bits at a time. The processor has a Carry flag that is set when the result of adding two numbers overflows the Accumulator. The processor adds that in when doing an addition, so it can be used to "carry the 1" assuming you start with the lowest-order byte of a number. A multi-byte add on the 6502 looks like this:

Clear carry flag (CLC)

Load lowest-order-byte of first number (LDA, load accumulator)

Add lowest-order-byte of second number (ADC, add with carry)

Store lowest-order byte of result (STA, store accumulator)

Repeat steps 2-4 with successively higher-order bytes

If at the end, the carry is set, you have overflowed; take appropriate action, such as generating an error message (BCS/BCC, branch if carry set/clear)

Subtraction is similar except you set the carry first, use the SBC instruction instead of ADC, and at the end the carry is clear if there was underflow.

But wait! What about negative numbers? Well, with the 6502 these are stored in a format called two's complement. Assuming an 8-bit number, -1 is stored as 255, because when you add 255 to something, you get one less in the Accumulator (plus a carry). -2 is stored as 254 and so on, all the way down to -128, which is stored as 128. So for signed integers, half the 0-255 range of a byte is used for positive numbers and half for negative numbers. (This convention lets you just check the high bit of a number to see if it's negative.)

Think of it like a 24-hour clock: adding 23 to the time will result in a time one hour earlier (on the next day). So 23 is the clock's modular equivalent to -1.

When you are using more than 1 byte you have to use larger numbers for negatives. For example, 16-bit integers have a range of 0-65536. So 65535 is used to represent -1, and so on, because adding 65535 to any number results in one less (plus a carry).

On the 6502 there are only four arithmetic operations: add, subtract, multiply by two (shift left), and divide by two (shift right). Multiplication and division can be done using only these operations when dealing in binary. For example, consider multiplying 5 (binary 101) and 3 (binary 11). As with decimal long multiplication, we start with the right digit of the multiplier and multiply 101 by 1, giving 101. Then we shift the multiplicand left and multiply 1010 by 1, giving 1010. Then we add these results together, giving 1111, or 15. Since we are ever only multiplying by 1 or 0, we don't really multiply; each bit of the multiplier simply serves as a flag which tells us whether to add the (shifted) multiplicand or not.

Division is analogous to manual long division using trial divisors, except in binary. If you are dividing by a constant, it is possible to do this in a way analogous to subtraction: rather than dividing by X, you multiply by a precalculated rendition of 1/X that produces the desired result plus an overflow. Even today, this is faster than division.

Here's a page showing some actual 6502 code for multiplication and division, including a nicely optimized multiplication routine that uses a 2 kilobyte lookup table. http://nparker.llx.com/a2/mult.html

Now try doing floating-point math in assembly, or converting floating-point numbers to nice output formats in assembly.  And do remember, it's 1979 and the clock speed is 1 MHz, so you must do it as efficiently as possible.

Things still work pretty much like this today, except with bigger word sizes and more registers, and of course most of the math is done by hardware now. But it's still done in the same fundamental way. If you add up the number of shifts and adds required for a multiply, for example, it correlates rather well to the number of cycles required for a hardware multiply instruction on early processors having such an instruction, such as the 6809, where it was performed in microcode in much the same way you would do it manually. (If you have a larger transistor budget, there are faster ways to do the shifts and adds, so modern processors do not perform these operations sequentially and can perform multiplications in as little as a single cycle.)

ContentLicense: CC BY-SA 3.0

ContentLicense: CC BY-SA 4.0


问:
What are the differences among the .NET certification exams?
I am a .NET developer using WPF and ASP.NET MVC and I was hoping to pass some kind of certification exam.

There seems to be four exams but I am unable to understand what the differences are even with Microsoft's definitions:

MCPD

MCAD

MCSD

MTA

How do they relate to each other? Is there a natural progression path through the certification exams? What version of .NET are they suited for?

答:
You need to define your career goals to be able to select the right certification path. Microsoft changed the way they certify professionals few years ago, and has focussed on providing a certification for a specific role.

Check this site:
http://www.microsoft.com/learning/career/en/us/default.aspx

You also need to decide the technology you are interested in (Web, WPF, Windows Forms, Cloud).

The real value you obtain is the learning process and the effort you put into learning the core subject.

Also, you may want to work as a Microsoft Certified Trainer (MCT).

As for training material, the sad part is, for the exams I took, MS books presented the subject to some extent but the questions were not even close to the questions in the MS books. However, this site may help you find training materials (the net is full of material):

MS Training Catalog

As said before, certifications should give a positive image about your interest in your career but they are not a substitute for solid knowledge and experience. However, some people don't believe in certifications.

OwnerDisplayName: John Mitchel


问:
Getting involved with an Open Source Project
I am heading into my senior year in computer engineering and have gotten a internship for this summer and fall. Since I will not be doing homework I would love to take this opportunity to get involved with an open source project of some sort. I am proficient with C, C++, Java, and Python. I am also reasonably familiar with Linux, using it on my laptop at the moment and all of my classes this semester focused on it.

I was considering taking a look at Android or Ubuntu but in the past I have felt a little overwhelmed. Does anyone have any advice? Interested on what would be a good project to work on, where to get started, and if I will really able to contribute much.

And in the end how often are peoples changes actually accepted? How often would I be writing code just to have it rejected?

tl:dr Looking for more programming experience by contributing to an open source project. New to the scene need advice.

答:
For example, Mozilla is always looking for C++ programmers for developing and testing their projects.  It is overwhelming for a new comer to download the massive code base and spend hours building it.  Then it takes in the neighborhood of six months where you spend an average 10+ hours a week to get acquainted with it and understand a bug or defect or such a thing.  Then, soon you should be able to understand how to look reproduce, isolate, fix, test, regression test, get the patch applied.  As you do this more, you may get direct write access to the code base, oversee a feature or so.  I believe this is true for every project that is mature with lots of people working on it.

On the other end, there are many projects dying because there is no one to develop them.  It could be hard to find people who can help you or documentation in these kinds of ones.

To strike a balance between these extremes, you can find a program that you need to use often or everyday.  Keep using it enough that you max out its feature set soon.  Perhaps develop some kind of affinity toward using it over other options.  Then, you could either submit a feature request or take it upon yourself as you are likely to be the one with most understanding of the feature you propose.  On the surface, this option makes you feel like you are never going to max out a program's features.  If you stay with it long enough, you will need the program to do more than what it can actually do.  It could be a security/privacy fix, or a subtle thing or a usability improvement.


问:
Robust way to keep records of software releases?
We release a number of small plug-ins that go along with our software.  Each plug-in allows our software to talk to a single manufactuer's hardware.  I would like to devise a system for keeping track of plug-in releases.

Example info that should be stored:

Hardware manufacturer name

32-bit? 64-bit? both?

What modes of operation does the hardware support?

What versions of the manufacturer's driver have been tested with the plugin?

Desirable properties of the system:

Able to synchronize with version control software

Stores data in human-readable text file (also good for differ tool)

Free visual, spreadsheet-like editor available

Able to do simple analysis like "What is the oldest plug-in?"

I've got to imagine that someone else has tackled this problem already.  Right now my best guess is XML/JSON with a visual editor, but I have been disappointed in the editors I've tried so far.  I'd like to get input from some more experienced developers.  Thanks!

答:
Continuous integration is probably something you'd find useful for this task.

I'd recommend you have a look at Hudson (or Jenkins1).

Essentially it's a build robot, and you can arbitrarily add scripts and activities to be run as part of the build process. For example, monitor the SCM repository for changes and trigger a build, run unit tests, log information about the build, etc. etc.

If you send log entries to a database (e.g. SQlite) you'll be able to do any queries you like.

1. the Hudson/Jenkins split.


答:
There are a lot of good answers here. You started with the right idea, too: complex operations like multiplication are built from simpler operations. As you guessed, there are faster ways of multiplying without a multiplication instruction than using a series of additions. Any multiplication can be implemented as the sum of smaller multiplications, or as a combination of shifts and additions. Examples:

```<code>a = 5 + 5 + 5 + 5 + 5;           // 5*5, but takes 5 operations
b = (5 << 2) + 5;                // 5*5 in only 2 operations
c = (41 << 4) + (41 << 2) + 41   // 41*21 in 4 operations
</code>```

Division can likewise be broken down into smaller operations. XOR (^) is a built-in instruction on every processor I've ever looked at, but even so it can be implemented as a combination of AND, OR, and NOT.

I have a feeling, though, that specific answers will be less satisfying to you than a general idea of the kinds of instructions a processor provides and how those instructions can be combined into more complex operations. There's nothing better for that kind of curiosity than a healthy dose of assembly language. Here's a very approachable introduction to MIPS assembly language.

Title: How is fundamental mathematics efficiently evaluated by programming languages?

Body:
As I get more and more involved with the theory behind programming, I find myself fascinated and dumbfounded by seemingly simple things..
I realize that my understanding of the majority of fundamental processes is justified through circular logic

Q: How does this work?

A: Because it does!

I hate this realization! I love knowledge, and on top of that I love learning, which leads me to my question (albeit it's a broad one).

Question:

How are fundamental mathematical operators assessed with programming languages?

How have current methods been improved?

Example

```<code>var = 5 * 5;
</code>```

My interpretation:

```<code>$num1 = 5; $num2 = 5; $num3 = 0;
while ($num2 > 0) {
    $num3 = $num3 + $num1;
    $num2 = $num2 - 1;
}
echo $num3;
</code>```

This seems to be highly inefficient. With Higher factors, this method is very slow while the standard built in method is instantanious. How would you simulate multiplication without iterating addition?

```<code>var = 5 / 5;
</code>```

How is this even done? I can't think of a way to literally split it 5 into 5 equal parts.

```<code>var = 5 ^ 5;
</code>```

Iterations of iterations of addition?
My interpretation:

```<code>$base = 5;
$mod = 5;
$num1 = $base;
while ($mod > 1) {

    $num2 = 5; $num3 = 0;
    while ($num2 > 0) {
        $num3 = $num3 + $num1;
        $num2 = $num2 - 1;
    }
    $num1 = $num3;
    $mod -=1;
}
echo $num3;
</code>```

Again, this is EXTREMELY inefficient, yet I can't think of another way to do this.
This same question extends to all mathematical related functions that are handled automagically.

Body:
There are a lot of good answers here. You started with the right idea, too: complex operations like multiplication are built from simpler operations. As you guessed, there are faster ways of multiplying without a multiplication instruction than using a series of additions. Any multiplication can be implemented as the sum of smaller multiplications, or as a combination of shifts and additions. Examples:

a = 5 + 5 + 5 + 5 + 5;           // 5*5, but takes 5 operations
b = (5 << 2) + 5;                // 5*5 in only 2 operations
c = (41 << 4) + (41 << 2) + 41   // 41*21 in 4 operations

Division can likewise be broken down into smaller operations. XOR (^) is a built-in instruction on every processor I've ever looked at, but even so it can be implemented as a combination of AND, OR, and NOT.

I have a feeling, though, that specific answers will be less satisfying to you than a general idea of the kinds of instructions a processor provides and how those instructions can be combined into more complex operations. There's nothing better for that kind of curiosity than a healthy dose of assembly language. Here's a very approachable introduction to MIPS assembly language.


问:
How to determine the levels of abstraction
I was reading a book today called "Clean code" and I came across a paragraph were the author was talking about the levels of abstraction per a function, he classified some code as low/intermediate/high level of abstraction.

My question is what is the criteria for determining the level of abstraction?

I quote the paragraph from the book:

In order to make sure our functions are doing “one thing,” we need to make sure that the
  statements within our function are all at the same level of abstraction. It is easy to see how
  Listing 3-1 violates this rule. There are concepts in there that are at a very high level of
  abstraction, such as getHtml(); others that are at an intermediate level of abstraction, such
  as: String pagePathName = PathParser.render(pagePath); and still others that are remarkably
  low level, such as: .append("\n").

答:
My question is what is the criteria for determining the level of abstraction?

The abstraction level is supposed to be obvious.  It's abstract if it's part of the problem domain -- not part of the programming language.   It's hard to be more clear than "highly abstract" == "not real" == "problem domain".  And "not abstract == concrete == part of the language".  It's supposed to be trivial to decide the abstraction level.  There's not supposed to be any subtlety at all.

.append("\n") is not abstract.  It just puts a character onto a string.  That would be concrete.  Not abstract.

String pagePathName = PathParser.render(pagePath); deals with Strings.  Concrete things.  Partly on concrete programming language features.  Partly working with abstract "path" and "parser" concepts.

getHtml();  Abstract.  Deals with "Markup" and things that aren't trivial, concrete, language features.

Abstract == not a language feature.

Concrete == a language feature.


答:
The author explains that in the "Reading Code from Top to Bottom" subsection of the part that talks about abstractions (hierarchical indentation mine):

[...] we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.

To include the setups and teardowns, we include setups, then we include the test page content, and then we include the teardowns.

To include the setups, we include the suite setup if this is a suite, then we include the regular setup.

To include the suite setup, we search the parent hierarchy for the "SuiteSetUp" page and add an include statement with the path of that page.

To search the parent ...

The code that'd go along with this would be something like this:

```<code>public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}
</code>```

And so on. Every time you go deeper down the function hierarchy, you should be changing levels of abstraction. In the example above, IncludeSetups, IncludeTestPageContent and IncludeTeardowns are all at the same level of abstraction.

In the example given in the book, the author's suggesting that the big function should be broken up into smaller ones that are very specific and do one thing only. If done right, the refactored function would look similar to the examples here. (The refactored version is given in Listing 3-7 in the book.)

Title: How to determine the levels of abstraction

Body:
I was reading a book today called "Clean code" and I came across a paragraph were the author was talking about the levels of abstraction per a function, he classified some code as low/intermediate/high level of abstraction.

My question is what is the criteria for determining the level of abstraction?

I quote the paragraph from the book:

In order to make sure our functions are doing “one thing,” we need to make sure that the
  statements within our function are all at the same level of abstraction. It is easy to see how
  Listing 3-1 violates this rule. There are concepts in there that are at a very high level of
  abstraction, such as getHtml(); others that are at an intermediate level of abstraction, such
  as: String pagePathName = PathParser.render(pagePath); and still others that are remarkably
  low level, such as: .append("\n").

Body:
The author explains that in the "Reading Code from Top to Bottom" subsection of the part that talks about abstractions (hierarchical indentation mine):

[...] we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.

To include the setups and teardowns, we include setups, then we include the test page content, and then we include the teardowns.

To include the setups, we include the suite setup if this is a suite, then we include the regular setup.

To include the suite setup, we search the parent hierarchy for the "SuiteSetUp" page and add an include statement with the path of that page.

To search the parent ...

The code that'd go along with this would be something like this:

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

And so on. Every time you go deeper down the function hierarchy, you should be changing levels of abstraction. In the example above, IncludeSetups, IncludeTestPageContent and IncludeTeardowns are all at the same level of abstraction.

In the example given in the book, the author's suggesting that the big function should be broken up into smaller ones that are very specific and do one thing only. If done right, the refactored function would look similar to the examples here. (The refactored version is given in Listing 3-7 in the book.)


答:
I think to understand this question, you need to understand what an abstraction is.  (I'm too lazy to find a formal definition, so I'm sure I'm about to get dinged, but here goes...) An abstraction is when you take a complex subject, or entity and hide most of its details while exposing the functionality that still defines the essence of that object.

I believe the example the book gave you was a house. If you take a very detailed look at the house, you'll see that it's made of boards, nails, windows, doors...  But a cartoon drawing of a house next to a photograph is still a house, even though it is missing many of those details.

Same thing with software.  Whenever you program, just like the book advises, you need to think about your software as layers.  A given program can easily have well over a hundred layers.  At the bottom, you might have assembly instructions which run on a CPU, at a higher level these instructions might be combined to form disk I/O routines, at a yet a higher level, you don't need to work with Disk I/O directly because you can use Windows functions to simply Open/Read/Write/Seek/Close a file.  These are all abstractions even before you get to your own application code.

Within your code, the abstraction layers continue.  You might have lower-level string/network/data manipulation routines.  At a higher level you might combine those routines into subsystems that define user management, UI layer, database access.  Yet another layer these subsystems might be combined into server components that come together to become part of a larger enterprise system.

The key to each of these abstraction layers is that each one hides the details exposed by the previous layer(s) and presents a very clean interface to be consumed by the next layer up. To open a file, you shouldn't have to know how to write individual sectors or what hardware interrupts to process. But if you start travel down the abstraction layer chain, you will definitely be able to trace from Write() function call, all the way down to the exact instruction that is sent to the hard drive controller.

What the author is telling you to do is when you define a class or a function, think about what layer you are one.  If you have a class that is managing subsystems and user objects, the same class should not be performing low level string manipulation or contain a whole bunch of variables just for making socket calls.  That would be the violation of crossing abstraction layers and also of having one class/function do only one thing (SRP - Single Responsibility Principle).


问:
Understanding Cyclomatic Complexity
I've recently come across Cyclomatic Complexity and I'd like to try to understand it better.

What are some practical coding examples of the different factors that go into calculating the complexity? Specifically, for the Wikipedia equation of M = E − N + 2P, I want to better understand what each of the following terms means:

E = the number of edges of the graph

N = the number of nodes of the graph

P = the number of connected components

I suspect that either E or N may be the number of decision points (if, else if, for, foreach, etc) in a block of code, but I'm not quite sure which is which or what the other signifies. I'm also guessing that P refers to function calls and class instantiations, but there isn't a clear definition given that I can see. If someone could shed a little more light with some clear code examples of each, it would help.

As a follow-up, does the Cyclomatic Complexity directly correlate to the number of unit tests needed for 100% path coverage? As an example, does a method with a complexity of 4 indicate that 4 unit tests are needed to cover that method?

Finally, do regular expressions affect Cyclomatic Complexity, and if so, how?

答:
Regarding the formula: nodes represent states, edges represent state changes. In every program, statements bring changes in the program state. Each consecutive statement is represented by an edge, and the state of the program after (or before...) the execution of the statement is the node.

If you have a branching statement (if for example) - then you have two nodes coming out, because the state can change in two ways.

Another way to calculate the Cyclomatic Complexity Number (CCN) is to calculate how many "regions" in the execution graph you have (where "independent region" is a circle that doesn't contain other circles). In this case the CCN will be the number of independent regions plus 1 (which would be exactly the same number as the previous formula gives you).

The CCN is used for branching coverage, or path coverage, which is the same. The CCN equals to the number of different branching paths theoretically possible in a single threaded application (that may include branches like "if x < 2 and x > 5 then", but that should be caught by a good compiler as an unreachable code). You have to have at least that number of different test cases (can be more since some test cases might be repeating paths covered by previous ones, but not less assuming each case covers a single path). If you cannot cover a path with any possible test case - you found unreachable code (although you'll need to actually prove to yourself why it is unreachable, probably some nested x < 2 and x > 5 lurking somewhere).

As to regular expressions - of course they affect, as any other piece of code. However, the CCN of the regex construct is probably too high to cover in a single unit test, and you can assume that the regex engine has been tested, and ignore the expressions' branching potential for your testing needs (unless you're testing your regex engine, of course).

Title: Understanding Cyclomatic Complexity


问:
What are the advantages of prototype-based OOP over class-based OOP?
When I first started programming Javascript after primarily dealing with OOP in context of class-based languages, I was left confused as to why prototype-based OOP would ever be preferred to class-based OOP.

What are the structural advantages to using prototype-based OOP, if any?  (e.g. Would we expect it to be faster or less memory intensive in certain applications?)

What are the advantages from a coder's perspective?  (e.g. Is it easier to code certain applications or extend other people's code using prototyping?)

Please don't look at this question as a question about Javascript in particular (which has had many faults over the years that are completely unrelated to prototyping).  Instead, please look at it in context of the theoretical advantages of prototyping vs classes.

Thank you.

答:
I had quite a lot of experience of the both approaches when writing an RPG game in Java. Originally I wrote the whole game using class-based OOP, but eventually realised that this was the wrong approach (it was becoming unmaintainable as the class hierarchy expanded). I therefore converted the whole code base to prototype-based code. The result was much better and easier to manage.

Source code here if you are interested (Tyrant - Java Roguelike)

Here are the main benefits:

It's trivial to create new "classes" - just copy the prototype and change a couple of properties and voila... new class. I used this to define new type of potion for example in 3-6 lines of Java each. Much better than a new class file and loads of boilerplate!

It's possible to build and maintain extremely large numbers of "classes" with comparatively little code - Tyrant for example had something like 3000 different prototypes with only about 42,000 lines of code total. That's pretty amazing for Java!

Multiple inheritance is easy - you just copy a subset of the properties from one prototype and paste them over the properties in another prototype. In an RPG for example, you might want a "steel golem" to have some of the properties of a "steel object" and some of the properties of a "golem" and some of the properties of an "unintelligent monster". Easy with prototypes, try doing that with an inheritance heirarchy......

You can do clever things with property modifiers - by putting clever logic in the generic "read property" method, you can implement various modifiers. For example, it was easy to define a magic ring that added +2 strength to whoever was wearing it. The logic for this was in the ring object, not in the "read strength" method, so you avoided having to put lots of conditional tests elsewhere in your code base (e.g. "is the character wearing a ring of strength increase?")

Instances can become templates for other instances - e.g. if you want to "clone" an object it is easy, just use the existing object as the prototype for the new object. No need to write lots of complex cloning logic for different classes.

It's quite easy to change behaviour at runtime - i.e. you can change an properties and "morph" an object pretty much arbitrarily at runtime. Allows for cool in-game effects, and if you couple this with a "scripting language" then pretty much anything is possible at runtime.

It's more suited to a "functional" style of programming - you tend to find yourself writing lots of functions that analyse objects an act appropriately, rather than embedded logic in methods attached to specific classes. I personally prefer this FP style.

Here are the main drawbacks:

You lose the assurances of static typing - since you are effectively creating a dynamic object system. This tends to mean that you need to write more tests to ensure behaviour is correct and that objects are of the right "kind"

There is some performance overhead - since reads of object properties are generally forced to go through one or more map lookups, you pay a slight cost in terms of performance. In my case it wasn't a problem, but it could be an issue in some cases (e.g. a 3D FPS with a lot of objects being queried in every frame)

Refactorings don't work the same way - in a prototype based system you are essentially "building" your inheritance heirarchy with code. IDEs / refactoring tools can't really help you since they can't grok your approach. I never found this a problem, but it could get out of hand if you are not careful. You probably want tests to check that your inheritance hierarchy is being constructed correctly!

It's a bit alien - people used to a conventional OOP style may easily get confused. "What do you mean there's only one class called "Thing"?!?" - "How do I extend this final Thing class!?!" - "You are violating OOP principles!!!" - "It's wrong to have all these static functions that act on any kind of object!?!?"

Finally some implementation notes:

I used a Java HashMap for properties and a "parent" pointer for the prototype. This worked fine but had the following downsides: a) property reads sometimes had to trace back through a long parent chain, hurting performance b) if you mutated a parent prototype, the change would affect all children that had not overriden the changing property. This can cause subtle bugs if you are not careful!

If I was doing this again, I would use an immutable persistent map for the properties (kind of like Clojure's persistent maps), or my own Java persistent hash map implementation. Then you would get the benefit of cheap copying / changes coupled with immutable behaviour and you wouldn't need to permanently link objects to their parents.

You can have fun if you embed functions / methods into object properties. The hack that I used in Java for this (anonymous subtypes of a "Script" class) wasn't very elegant - if doing this again I'd probably use a proper easily-embeddable language for scripts (Clojure or Groovy)


问:
Is there such a thing as too much asynchronous code?
I am at the moment messing around with clients and servers in C# winforms and I'm trying to implement it all asynchronously. However, I'm beginning to wonder, should I use asynchronous code for everything?

Here's a list of what I'm doing asynchronously at the moment:

TcpClient.BeginConnect with TcpClient.EndConnect

NetworkStream.BeginRead with NetworkStream.EndRead

TcpListener.BeginAcceptTcpClient with TcpListener.EndAcceptTcpClient

Listening thread on server for client connections

Listening thread on client for incoming data from server

Listening Task on server for incoming data from each client

New Task created every time an event such as ConnectionLost is raised (so the respective form can update). Think Delegate.BeginInvoke.

Everything is set up asynchrously and it works well, but I'm beginning to wonder if all of these should be asynchronous. I mean, it all sounds nice and people claim it to be efficient due to IO completion ports not blocking or something, but is it really?

I can understand having a single thread for listening on both the client and server, and for reading it makes sense as well. But every time an event is raised (which may be quite often!), should its invocation really be asynchronous? It seems like I am using Tasks for everything that can be made asynchronous and I'm not sure whether or not that is best practice.

答:
Yes, it really is more efficient to do all this stuff asynchronously. If you do it synchronously then you're constantly polling, which wastes resources and can cause you to miss events if you don't process them quickly enough.

In addition, if you tried to do all that stuff synchronously, you'll find yourself mired in silly synchronization problems, trying to shuffle priorities, weird edge cases that come up when a client tries to connect within 22 msec of another client disconnecting, but only on Thursdays when there's a full moon.

With your current design, each logically separable task is separated from the rest of the program. It was likely easier to write, and it will be a whole lot easier to debug if something goes wrong. And maintenance is easier, too, because it's impossible (okay, very difficult) to get confused and modify the wrong thing. Having worked on systems like this that were not asynchronous, I can attest that it's incredibly easy to think you're diddling the input buffer when in fact you're mangling the output buffer.

As to your final question: yes, you really should raise every event asynchronously. Responding to an event can take an arbitrarily long amount of time. If you write it so that responding to the event is done synchronously, and that response takes a long time (which, in a communications app like this, could be five seconds or less), then you're going to miss events.

The asynchronous model you're using is very much like an implicit queue. It can tolerate spikes in traffic that would overwhelm a synchronous system. As long as, on average, you can process traffic faster than it comes in, you're fine. With a synchronous system, too many signals at once, or too many signals that take a long time to process, will kill the application. With the asynchronous model, the only way to kill the application is to overflow the queue.

OwnerDisplayName: Jim Mischel


答:
From the question, it sounds like you have concerns about the performance of asynchronous operations in certain circumstances. Asynchronous operations are incredibly fast and efficient because under the covers .NET uses thread pools: The threads to execute the code already exist and thus there is basically no penalty for picking one of these and executing some code on it.

While on the other hand, the performance gains to be had for async are huge. Synchronous methods will sit on a thread waiting for some I/O operation to complete like a disk read or a network call. Since I/O operations typically take far longer to complete than actual CPU computation, that thread is doing nothing for basically its entire existence. This is bad for two reasons. Threads typically cost around 1MB of memory and when you have a lot of threads around that are all blocking on long-running I/O operations, you get a lot of expensive context switching as threads are swapped in and out of the CPU.

The upshot is that there are basically never any performance problems from using asynchronous methods. The only downside is the increase in code complexity, but the C# async/await pattern coming in C# 5.0 (linked earlier) looks like it's going to basically eliminate the hassle typically associated with async.

Title: Is there such a thing as too much asynchronous code?

Body:
I am at the moment messing around with clients and servers in C# winforms and I'm trying to implement it all asynchronously. However, I'm beginning to wonder, should I use asynchronous code for everything?

Here's a list of what I'm doing asynchronously at the moment:

TcpClient.BeginConnect with TcpClient.EndConnect

NetworkStream.BeginRead with NetworkStream.EndRead

TcpListener.BeginAcceptTcpClient with TcpListener.EndAcceptTcpClient

Listening thread on server for client connections

Listening thread on client for incoming data from server

Listening Task on server for incoming data from each client

New Task created every time an event such as ConnectionLost is raised (so the respective form can update). Think Delegate.BeginInvoke.

Everything is set up asynchrously and it works well, but I'm beginning to wonder if all of these should be asynchronous. I mean, it all sounds nice and people claim it to be efficient due to IO completion ports not blocking or something, but is it really?

I can understand having a single thread for listening on both the client and server, and for reading it makes sense as well. But every time an event is raised (which may be quite often!), should its invocation really be asynchronous? It seems like I am using Tasks for everything that can be made asynchronous and I'm not sure whether or not that is best practice.

OwnerDisplayName: RandomEngy


问:
Binaries in source control
When developing for embedded devices and other odd worlds, it's very likely your build process will include multiple proprietary binaries, using very specific versions of them.
So the question is, are they part of your source control? My offices goes by the rule of "checking out from source control includes everything you need to compile the code" and this has led to some serious arguments.

The main arguments I see against this is bloating the source control DB, the lack of diffing binary files (see prior questions on the subject). This is against the ability to check out, build, knowing you have the precise environmental the previous developer intended and without hunting down the appropriate files (with specific versions no less!)

答:
It's very chaos to check-in binary to SCM in my mind. I had run a very complex project, which has a lot of dependencies to third part libraries. The  principles that we adopted:

All source code is managed with SCM

All dependencies are managed
with Ivy, which has great eclipse integration.

This works pretty well. We have a configuration file about version of each external library that source code can be compiled with. This configuration file is checked into SCM, so it evolves as source code evolves. By applying this approach, we can exactly reproduce a build without messing around version of external libraries.

Title: Binaries in source control


问:
what is "graceful degradation"?
I hear a lot about this term "Graceful degradation".

For example ,

```<code> "An application server should gracefully degrage when it is under heavy load "

  "Graceful degradation of user interfaces.... "
</code>```

The term looks like an abstract thing to me. Any concrete example of what it means?

答:
Applications that have a "degraded" mode generally offer access to a limited set of features due to an internal or external problem. For example, imagine that your application connects to two different data sources. If one of these fails it could still be possible for it to continue running but to disable all visual (or/and backend) features related to the unavailable resource.

Concrete example: your application has two data sources, in one of them you store persons, in the other you store accounts. Even if the account database fails, if the application has a degraded mode, you should still be able to create new persons, albeit not interact with their accounts.

As to the user interface, this generally means that you clearly indicate to the user that some features are disabled, and display some warning message so that he is not left out in the dark as to why something is unavailable.

Also, there is a Wikipedia entry related to fault-tolerant systems.

Title: what is "graceful degradation"?


答:
With technology advancement we always have changes rolling into a application which at all times may not be supported by all target audiences. In such scenarios we come across Graceful degradation which emulates that we build for the best available but we also have a fail safe for those who have not upgraded or their system might not support.

One major example is the  tag which has the alt attribute which is helpful for cases where images are blocked or are turned off, now these give some meaningful context for the images(of course only if we specify).

Well another example i can think of are of stylesheets in case of a error or unavailability the browser provides a generic version of its own for showing/displaying the page.

Now as you mentioned heavy load you have to carefully chalk out a plan as what is to be done if your hits shoot past the threshold, you disable certain features or suspend some services which are not critical and give you a breather. All this will help you set up a graceful degradation so that the user knows due the x things the server might take some time to respond or the x service would be unavailable for an hour or so

Title: what is "graceful degradation"?

Body:
I hear a lot about this term "Graceful degradation".

For example ,

```<code> "An application server should gracefully degrage when it is under heavy load "

  "Graceful degradation of user interfaces.... "
</code>```

The term looks like an abstract thing to me. Any concrete example of what it means?

Body:
With technology advancement we always have changes rolling into a application which at all times may not be supported by all target audiences. In such scenarios we come across Graceful degradation which emulates that we build for the best available but we also have a fail safe for those who have not upgraded or their system might not support.

One major example is the <img> tag which has the alt attribute which is helpful for cases where images are blocked or are turned off, now these give some meaningful context for the images(of course only if we specify).

Well another example i can think of are of stylesheets in case of a error or unavailability the browser provides a generic version of its own for showing/displaying the page.

Now as you mentioned heavy load you have to carefully chalk out a plan as what is to be done if your hits shoot past the threshold, you disable certain features or suspend some services which are not critical and give you a breather. All this will help you set up a graceful degradation so that the user knows due the x things the server might take some time to respond or the x service would be unavailable for an hour or so


答:
Here are some examples:

If you run out of some resource (handles, sockets, memory, drive space) you don't crash but rather you keep serving as many users as you can serve with your available resources.  Something that doesn't degrade gracefuly may simply stop working when taken outside the design envelope.

Under loads heavier than what you designed for users will experience slower response than what you designed for.  Without graceful degradation having the system stop working once the requirements are exceeded may be acceptable.

Error conditions, such as disk drive failure, failure in a CPU core, failure in memory.  A system designed to degrade gracefully may continue working in some reduced mode (e.g. without being able to access data in the failed drive but still delivering data from the drive that hasn't failed) while another will simply crash.

Title: what is "graceful degradation"?


答:
It means that as inputs and state exceed design limits, outputs remain as reasonable and reliable as possible.

If it's a server designed to handle 100 simultaneous connections, it doesn't crash or start returning crazy results at 101 or even 150 connections -- it slows down or maybe drops a few connections, but continues mostly working. If it's a database designed to handle 1 billion records, it doesn't suddenly slow down to an unusable state at 1.01 billion.

Title: what is "graceful degradation"?


答:
If you have no graphical system (like no X11 server running), your program should at least provide a CLI, like ncurses.

vi has a dumb mode in which it behaves like ex, if the terminal has too few features.

Title: what is "graceful degradation"?


答:
As a follow-up, does the Cyclomatic Complexity directly correlate to the number of unit tests needed for 100% path coverage?

Yes, basically.  It's also a good idea to make use of cyclomatic complexity as an indicator of when to refactor.  In my experience, testability and reusability greatly increase for lower CC (although you should be practical - don't over-refactor, and some methods will have high CC due to their nature - it doesn't always make sense to try and force it lower).

Finally, do regular expressions affect Cyclomatic Complexity, and if so, how?

Yes, if you want to be exact, although most code analysis tools don't seem to take them into consideration in that way.  Regular expressions are just finite state machines, so I'm guessing their CC could be calculated from the FSM graph, but it would be quite a large number.

Title: Understanding Cyclomatic Complexity

Body:
I've recently come across Cyclomatic Complexity and I'd like to try to understand it better.

What are some practical coding examples of the different factors that go into calculating the complexity? Specifically, for the Wikipedia equation of M = E − N + 2P, I want to better understand what each of the following terms means:

E = the number of edges of the graph

N = the number of nodes of the graph

P = the number of connected components

I suspect that either E or N may be the number of decision points (if, else if, for, foreach, etc) in a block of code, but I'm not quite sure which is which or what the other signifies. I'm also guessing that P refers to function calls and class instantiations, but there isn't a clear definition given that I can see. If someone could shed a little more light with some clear code examples of each, it would help.

As a follow-up, does the Cyclomatic Complexity directly correlate to the number of unit tests needed for 100% path coverage? As an example, does a method with a complexity of 4 indicate that 4 unit tests are needed to cover that method?

Finally, do regular expressions affect Cyclomatic Complexity, and if so, how?


问:
Interesting or unique types in programming languages?
We have all seen integer, floating point, string, and the occasional decimal type. What are some of the most strange or unique or useful types you have encountered, useful or not?</p>

答:
Clojure is interesting because it has a meta-concept of "abstractions" that pervade the language. Examples:

Collections

Sequences (lazy and non-lazy)

Higher Order Functions

Multimethods

Protocols

Managed references

Macros

various others.....

To some extent, the abstractions take the "single responsibility principle" to the extreme. It's up to you to compose them to get the functionality that you want, but you can be extremely flexible about how you glue them together.

For example, if you want a class-based OOP system with inheritance, you could build one out of these core abstractions relatively quickly.

In practice, the abstractions themselves are designed in a way that multiple implementations are possible, e.g. through specific interfaces like clojure.lang.ISeq for sequences or clojure.lang.IFn for higher order functions.

There's an interesting video about this topic: The Art of Abstraction

ContentLicense: CC BY-SA 2.5


问:
Does hierarchial inheritance belong to the past?
Recently it came to my attention that hierarchical inheritance may be a relic of thinking of classes as "structs with functions" rather than a product contract-driven mentality.

Consider, as a simple specimen the implementation of "Unmodifiable Iterator" from Guava. http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/UnmodifiableIterator.html It's an iterator which throws an "UnsupportedOperationException" on invocation of remove().

Now, I'm sure most people would agree that implementing a contract and then having one of its methods always throw an exception is bad form -- when you implement a contract you're implicitly guaranteeing that all the methods would work. Yet, what are our options here? We could declare an interface which does not contain the remove method but that would render our return type incompatible with all methods which work on iterators. We could blame the Java API designers for forcing the remove() method to be a part of every iterator, rather than moving it to a higher level interface such as "RemovableIterator".

If they did that it would indeed avoid some problems but let's say we need an iterator which can also set values called "SettableIterator" (implements setValue(T) ) and also a resettable iterator. If we require a combination of these functionalities we are forced to declare an interface for every combination. RessetableSettableIterator, RessetableRemovableIterator, RemovableSettableIterator , etc. The combinations grow exponentially to the extra features we add to the interface.

What we are usually trying to express is something like 'this function requires a parameter which is Iterable, Settable and Ressetable' or 'this function returns a value which is Iterable and Resettable'. Yet languages like C#, Java and C++ do not allow us to do this without very awkward use of generics.

Are there recent methods that make this kind of design obsolete?

答:
The answer to the title question is objectively no. There are a number of paradigms in software development, and inheritance-driven OOP is among the most successful because it works well for a great many problems. That doesn't mean that there's no room for new paradigms, or that they won't also find some success.

Whatever the merits of any new paradigms or the drawbacks of inheritance, inertia alone will guarantee that inheritance will be with us for some time to come. And the fact that as of this writing you haven't clearly articulated the alternative that's supposed to be the subject of your question leads me to believe that its successor is not immediately apparent.


问:
Is there any reason lazy initialization couldn't be built into Java?
Since I'm working on a server with absolutely no non-persisted state for users, every User-related object we have is rolled out on every request.

Consequently I often find myself doing lazy initialization of properties of objects that may go unused.

protected EventDispatcher dispatcher = new EventDispatcher();

Becomes...

```<code>protected EventDispatcher<EventMessage> dispatcher;

public EventDispatcher<EventMessage> getEventDispatcher() {
    if (dispatcher == null) {
        dispatcher = new EventDispatcher<EventMessage>();
    }
    return dispatcher;
}
</code>```

Is there any reason this couldn't be built into Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();

As mentioned below in the comments, I realize a language could theoretically evolve to include most anything you want.  I'm looking for a practical measurement of possibility. Would this conflict with other features? Is the implementation simple enough to work well with the JVM as it exists?  And even, is it a good idea?

答:
Here is an eight page answer to your question:
http://tinlizzie.org/~awarth/papers/fool07.pdf

If i can try and coarsely summarize the problems with adding laziness, it's the corner cases.
There are a lot of caveats around side-effects. Consider, in your example, if the constructor had visible side-effects like bumping a global counter or doing I/O... It's hard to reason about when that would happen. Or consider even uglier side-effects about exceptions (they're thrown ... when you reference the lazy object?)

Just skip to section 6 in the above paper.  (And admire all the type system formal logic on the pages you skip ...)


答: If you want a language with a unique type then head for BCPL.  This language only has one data type, the word, being a fixed number of bits for the language implementation.</p>

Title: Interesting or unique types in programming languages?

Body: We have all seen integer, floating point, string, and the occasional decimal type. What are some of the most strange or unique or useful types you have encountered, useful or not?</p>


问:
To Domain or not to Domain
The SQL92 and SQL99 standards define CREATE DOMAIN DDL constructs. Not all databases support this, or have a different name for it (SQL Server has User Defined Types, for example).

These allow one to define a constrained data-type to be used in their database, to simplify and enforce rules pertaining to the allowed values. Such a data-type could be used in column declarations, in inputs and outputs to stored procedures and functions etc...

I would like to know:

Do people actually use domains in their database designs?

If so to what extent?

How useful are they?

What pitfalls have you encountered?

I am trying to asses the viability of using these in future database development.

答:
When you say "not all databases support this", I think a better way of putting it is the following :

Every major database supports this, as they support triggers, functions and other advanced features extensively.

This brings us to the conclusion that this is part of advanced SQL and makes sense at some point.

```<code>Do people actually use domains in their database designs?
</code>```

The less possible, due to the extensive coverage required (considering operators, indexes, etc.)

```<code>If so to what extent?
</code>```

Again, as limited as can be, if an existing type combined with a little additional defined logic (i.e. checks etc.) can do the trick, why go that far ?

```<code>How useful are they?
</code>```

A whole lot.  Let's consider for one second a not-so-good DBMS like MySQL, which I picked for this example for one reason : it lacks good support for the inet (IP address) type.

Now you want to write an application that is mostly focused on IP data like ranges and all that, and you're stuck with the default type and its limited functionality, you will either write additional functions and operators (like those supported natively in postgreSQL for example) or write much more complex queries for every functionality you need.

This is a case where you will easily justify the time spent on defining your own functions (inet >> inet in PostgreSQL : range contained in range operator).

At that point, you have already justified extending datatype support, there is only one other step to defining a new datatype.

Now back to PostgreSQL which has real nice type support but no unsigned int .. which you need, because you're really concerned about storage / performance (who knows ...), well you'll need to add it as well as the operators - although of course this is mostly deriving existing int operators.

```<code>What pitfalls have you encountered?
</code>```

I don't play around with that as so far I haven't had a project that both required and justified the time required for this.

The biggest issues I can see coming with that would be reinventing the wheel, introducing bugs in the "safe" layer (db), incomplete type support which you'll only realize months later when your CONCAT(cast * AS varchar) fails because you did not define a cast(newtype as varchar), etc.

There are answers talking about "uncommon" etc. Definitely these are and should be uncommon (otherwise it means the dbms lacks a lot of important types), but on the other hand, one should remember that a (good) db is ACID compliant (unlike an application) and that anything related to consistency is better kept in there.

There are many cases where business logic is handled in the software layer and it could be done in SQL, where it's safer.  App developers tend to feel more comfortable within the application layer and often avoid better solutions implemented in SQL, this should not be considered as good practice.

UDT's can be a good solution for optimization, a good example is given in another answer about the m/f type using char(1). If it had been a UDT it could be a boolean instead (unless we want to offer the third and fourth options). Of course we all know this isn't really optimization because of the column overhead, but the possibility is there.

Title: To Domain or not to Domain

Body:
When you say "not all databases support this", I think a better way of putting it is the following :

Every major database supports this, as they support triggers, functions and other advanced features extensively.

This brings us to the conclusion that this is part of advanced SQL and makes sense at some point.

Do people actually use domains in their database designs?

The less possible, due to the extensive coverage required (considering operators, indexes, etc.)

If so to what extent?

Again, as limited as can be, if an existing type combined with a little additional defined logic (i.e. checks etc.) can do the trick, why go that far ?

How useful are they?

A whole lot.  Let's consider for one second a not-so-good DBMS like MySQL, which I picked for this example for one reason : it lacks good support for the inet (IP address) type.

Now you want to write an application that is mostly focused on IP data like ranges and all that, and you're stuck with the default type and its limited functionality, you will either write additional functions and operators (like those supported natively in postgreSQL for example) or write much more complex queries for every functionality you need.

This is a case where you will easily justify the time spent on defining your own functions (inet >> inet in PostgreSQL : range contained in range operator).

At that point, you have already justified extending datatype support, there is only one other step to defining a new datatype.

Now back to PostgreSQL which has real nice type support but no unsigned int .. which you need, because you're really concerned about storage / performance (who knows ...), well you'll need to add it as well as the operators - although of course this is mostly deriving existing int operators.

What pitfalls have you encountered?

I don't play around with that as so far I haven't had a project that both required and justified the time required for this.

The biggest issues I can see coming with that would be reinventing the wheel, introducing bugs in the "safe" layer (db), incomplete type support which you'll only realize months later when your CONCAT(cast * AS varchar) fails because you did not define a cast(newtype as varchar), etc.

There are answers talking about "uncommon" etc. Definitely these are and should be uncommon (otherwise it means the dbms lacks a lot of important types), but on the other hand, one should remember that a (good) db is ACID compliant (unlike an application) and that anything related to consistency is better kept in there.

There are many cases where business logic is handled in the software layer and it could be done in SQL, where it's safer.  App developers tend to feel more comfortable within the application layer and often avoid better solutions implemented in SQL, this should not be considered as good practice.

UDT's can be a good solution for optimization, a good example is given in another answer about the m/f type using char(1). If it had been a UDT it could be a boolean instead (unless we want to offer the third and fourth options). Of course we all know this isn't really optimization because of the column overhead, but the possibility is there.


答:
The primary purpose of interfaces is to enable reuse of calling code without having to rewrite it for every possible kind of Iterator (or whatever) object.  In your example, the Liskov substitution violation eliminates a good chunk of that code from being reused properly, but this particular interface is so extremely widespread that there is a significant amount of reusable code even with that elimination.  The alternative here is to redesign the hierarchy to take unmodifiable iterators into account, and in the process have to rewrite any existing code to use the new classes, some of which you may not have source for.  In other words, there are exceptions to every rule.

Also note that you do not have to declare a new interface for every possible combination, you can just require multiple interfaces.  You would not need a RemovableResettableIterator, just a RemovableIterator and ResettableIterator and require one or the other or both as appropriate.

Title: Does hierarchial inheritance belong to the past?

Body:
Recently it came to my attention that hierarchical inheritance may be a relic of thinking of classes as "structs with functions" rather than a product contract-driven mentality.

Consider, as a simple specimen the implementation of "Unmodifiable Iterator" from Guava. http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/UnmodifiableIterator.html It's an iterator which throws an "UnsupportedOperationException" on invocation of remove().

Now, I'm sure most people would agree that implementing a contract and then having one of its methods always throw an exception is bad form -- when you implement a contract you're implicitly guaranteeing that all the methods would work. Yet, what are our options here? We could declare an interface which does not contain the remove method but that would render our return type incompatible with all methods which work on iterators. We could blame the Java API designers for forcing the remove() method to be a part of every iterator, rather than moving it to a higher level interface such as "RemovableIterator".

If they did that it would indeed avoid some problems but let's say we need an iterator which can also set values called "SettableIterator" (implements setValue(T) ) and also a resettable iterator. If we require a combination of these functionalities we are forced to declare an interface for every combination. RessetableSettableIterator, RessetableRemovableIterator, RemovableSettableIterator , etc. The combinations grow exponentially to the extra features we add to the interface.

What we are usually trying to express is something like 'this function requires a parameter which is Iterable, Settable and Ressetable' or 'this function returns a value which is Iterable and Resettable'. Yet languages like C#, Java and C++ do not allow us to do this without very awkward use of generics.

Are there recent methods that make this kind of design obsolete?


问:
application architecture with one or more PDFs
I am writing an iPad application.  The main view of the application will be a PDF.  I have made considerable progress in parsing out the contents of the PDF.

The application will also have at least two "side views".  These side views may or may not themselves be driven by PDF files.  That is part of what I am trying to figure out.

The main PDF will contain some hidden buttons which cause the side view to show certain things.  For example, there might be a button over the name "Lincoln" that brings up a side view about Abe Lincoln, another one over the name "Washington" that brings up a side view about George Washington, and so on.  The creation of these hidden buttons should be driven by data in the main PDF.  I'm thinking this means annotations.

Two questions:

1) Is there one type of annotation that I might prefer over another?  Options I can see include actions, URIs, and maybe links -- but the last one could be complicated by the numerous internal links within the PDF.

2) Should I use PDFs for the side views?  What are the arguments, pro and con?

Considerations:

A)  Ease of moving the app to other platforms later

B)  Pirating.  I would prefer that someone who got my PDFs not be able to reproduce the app without some work.

EDIT: answering the questions posed in an answer:

By "action", I mean "PDF action".  See section 12.6 of the [http://www.adobe.com/devnet/pdf/pdf_reference.html](PDF specification).

The main view is a PDF because that's the format the content author is comfortable creating.  But since this PDF will be embedded in the app, I have to assume that it could escape "into the wild".

答:
1) URIs and links are universal, they're your friends and enable anything. what is an action for you ?

2) Why are you using a PDF in the center view ? is it some sort of PDF reader ?  If yes, why do you bother parsing instead of embedding existing pdf-readers ? If you're already using PDF for the center, why would it be any worse to use it on the side ??

A) If you're concerned about other platforms, why not make it web ?

B) All source code can be stolen, your app will always be much easier to copy than to write and if you want to keep your market share your only solution is to remain ahead in terms of customer perception (i.e. noone switches from your app to the copy and people switch from the copy to your app because you have the features first and it works better).


答: Googles Go has a "Channel" type which is quite unique.</p>


问:
What programs emit C++ code and pass it to mainstream compilers?
I suspect there're programs that instead of emitting machine code instead emit C++ code and then start a mainstream C++ compiler to compile it to machine code.

I can't find any notable examples except MIDL which emits some rather primitive code.

What are notable examples of such systems?

答:
It's possible with MATLAB/Simulink (you can choose C or C++ but C is more often use at least if the target is embedded).

Another example is ArgoUML  (open source UML modeling tool).


答:
The Eiffel compiler in EiffelStudio compiles to C (maybe with some C++ in it). One reason why it takes ages to compile even the simples Eiffel programs.

The Haskell compiler GHC used to target a C-like language C--. Today, it generates machine code directly. A backend targetting LLVM also exists.

Title: What programs emit C++ code and pass it to mainstream compilers?

Body:
I suspect there're programs that instead of emitting machine code instead emit C++ code and then start a mainstream C++ compiler to compile it to machine code.

I can't find any notable examples except MIDL which emits some rather primitive code.

What are notable examples of such systems?


答: HipHop from Facebook transforms PHP code into C++.


问:
How to include conditions in UML sequence diagrams?
I like to draw a UML sequence diagram to display the sequence of actions and interactions of different parts of my system (I think they called actors).

However, I need to include if then else statements here. Do I do something wrong? Can I use conditional if statements in my UML sequence diagram? How?

答:
As in many types of UML diagrams, you can use guards to denote a condition. A guard is a boolean expression that you can write over a transition.

Here's a picture with an example:

Notice the "[pastDueBalance = 0]" condition.

You can also use combined fragments for more complicated conditional logic. See this nice msdn article for further information.


答: If you were working with Debian packages, you could just do ls/find on your pool directory.

Title: Robust way to keep records of software releases?

Body:
We release a number of small plug-ins that go along with our software.  Each plug-in allows our software to talk to a single manufactuer's hardware.  I would like to devise a system for keeping track of plug-in releases.

Example info that should be stored:

Hardware manufacturer name

32-bit? 64-bit? both?

What modes of operation does the hardware support?

What versions of the manufacturer's driver have been tested with the plugin?

Desirable properties of the system:

Able to synchronize with version control software

Stores data in human-readable text file (also good for differ tool)

Free visual, spreadsheet-like editor available

Able to do simple analysis like "What is the oldest plug-in?"

I've got to imagine that someone else has tackled this problem already.  Right now my best guess is XML/JSON with a visual editor, but I have been disappointed in the editors I've tried so far.  I'd like to get input from some more experienced developers.  Thanks!


答:
Automatic code generation is common among design tools. For instance, you specify your design with UML, Statecharts or both and code is generated. You only have to fill in placeholders for implementing methods.

Examples of such tools are Rhapsody and Topcased.


问:
How much effort should we spend to programming for multiple cores?
Processors are getting more and more cores these days, which leaves me wondering...

Should we, programmers, adapt to this behaviour and spent more effort on programming for multiple cores?

To what extent should we do and optimize this? Thread? Affinity? Hardware optimizations? Something else?

答:
well, it really depends on what you are developing. the answer, depending on what you are developing, can range from "it's insignificant" to "it's absolutely critical, and we expect everyone in the team to have a good understanding and use of parallel implementations".

for most cases, a solid understanding and use of locks, threads, and tasks and task pools will be a good start when the need for parallelism is required. (varies by lang/lib)

add to that the differences in designs you must make - for nontrivial multiprocessing, one must often learn several new programming models, or parallelization strategies. in that case, the time to learn, to fail enough times to have a solid understanding, and to update existing programs can take a team a year (or more). once you have reached that point, you will (hopefully!) not percieve or approach problems/implementations as you do today (provided you have not made that transition yet).

another obstacle is that you're effectively optimizing a program for a certain execution. if you're not given much time to optimize programs, then you really won't benefit from it as much as you should. high level (or obvious) parallelization can improve your program's percieved speed with fairly little effort, and that's as far as many teams will go today: "We've parallelized the really obvious parts of the app" - that's fine in some cases. will the benefit of taking the low hanging fruit and using simple parallization be proportionate to the number of cores? oftentimes, when there are two to four logical cores but not so often beyond that. in many cases, that's an acceptable return, given the time investment. this parallel model is many people's introduction to implementing good uses of parallelism. it is commonly implemented using parallelized iteration, explicit tasks, simple threads or multitasking.

what you learn using this trivial parallel models will not be ideal in all complex parallel scenarios; effectively applying complex parallel designs requires a much different understanding and approach. these simple models are often detached or have trivial interaction with other components of the system. as well, many implementations of these trivial models do not scale well to effectively complex parallel systems - a bad complex parallel design can take as long to execute as the simple model. ill: it executes twice as fast as the single threaded model, while utilitzing 8 logical cores during execution. the most comon examples are using/creating too many threads and high levels of synchronization interference. in general, this is termed parallel slowdown. it's quite easy to encounter if you approach all parallel problems as simple problems.

so, let's say you really should utilize efficient multithreading in your programs (the minority, in today's climate): you'll need to employ the simple model effectively to learn the complex model and then relearn how you approach program flow and interaction. the complex model is where your program should ultimately be at since that's where hardware is today, and where the most dominant improvements will be made.

the execution of simple models can be envisioned like a fork, and the complex models operate like a complex, uh, ecosystem. i think understanding of simple models, including general locking and threading should be or will soon be expected of intermediate developers when the domain (in which you develop) uses it. understanding complex models is still a bit unusual today (in most domains), but i think the demand will increase quite quickly. as developers, much more of our programs should support these models, and most of use are quite far behind in understanding and implementing these concepts. since logical processor counts are one of the most important areas of hardware improvement, the demand for people who understand and can implement complex systems will surely increase.

finally, there are a lot of people who think the solution is just "add parallelization". oftentimes, it's better to make the existing implementation faster. it's much easier and much more straightforward in many cases. many programs in the wild have never been optimized; some people just had the impression that the unoptimized version would be eclipsed by hardware someday soon. improving the design or algos of existing programs is also an important skill if performance is important - throwing more cores at problems is not necessarily the best or simplest solution.

when targeting modern PCs, most of us who need to implement good parallel systems will not need to go beyond multithreading, locking, parallel libraries, a book's worth of reading, and a lot of experience writing and testing programs (basically, significantly restructuring how you approach writing programs).


答:
There are four possibilities I know of (with increasing power):

The easiest is just using guards, which are simple, side-effect free boolean expressions.

With combined fragments, you can group sets of messages together to show conditional flow in a sequence diagram (alternatives, options, loops)

Much more powerful is the Object Constraint Language (OCL), which can additionally quantify (for all, exists) and offers a full fledged (DesignBy-)Contract language (that is nearly as expressive as full first order logic).

The most powerful way is to express your constraint using a UML Action Language from Executable UML (xUML) that conforms to the UML Action Semantics.

My choice would be the least powerful one that is still sufficiently expressible for what you want to do. For instance, actions in 4. can have side-effects, which makes them much more fragile than OCL.

Title: How to include conditions in UML sequence diagrams?

Body:
I like to draw a UML sequence diagram to display the sequence of actions and interactions of different parts of my system (I think they called actors).

However, I need to include if then else statements here. Do I do something wrong? Can I use conditional if statements in my UML sequence diagram? How?


问:
How does a programmer used to static languages cope with lack of Javascript tooling
I have programmed pretty much exclusively in compiled languages, particularly Java, for most of my career.  One of my favourite things about Java is how productive you can be, and how little code you actually have to write, when using tools like Eclipse.

You can:

Easily and automatically refactor your methods and classes

View instantly all the places where a method is invoked, or a constant is used (Open Call Hierarchy/Show References)

Static typing means you can use code completion to show all the parameters/functions available on an object

Control-click on a function/member/class name to go straight to its definition

All these facilities make me feel like the IDE is my best friend.  Writing Java code and particularly understanding other peoples' programs becomes far easier.

However, I am being called on more and more to use Javascript, and my experience so far has been quite negative.

In particular:

No immediate way of finding a function's entry point
(other than a plain text search, which may then result in a subsequent searches for methods further up the call hierarchy, after two or three of which you've forgotten where you started)

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter
(other than actually running the program, navigating to the point at which the function is called, and using console.logs to output all the properties available)

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

The upshot is that you pretty much need to have the entire program in your head at all times.  This massively increases the cognitive load for writing complex programs.  And all this extra stuff to worry about leaves less room in my brain for actual creativity and problem solving.

Sure, it's faster to just throw an object together rather than write an entire formal class definition.  But while programs may be slightly easier and quicker to write, in my experience they are far harder to read and debug.

My question is, how do other programmers cope with these issues?  Javascript is clearly growing in popularity, and the blogs I read are about how productive people are being with it, rather than desperately trying to find solutions to these issues.

GWT allows you to write code for a Javascript environment in Java instead, but doesn't seem to be as widely used as I would expect; people actually seem to prefer Javascript for complex programs.

What am I missing?

答:
I used to dislike javascript (and its dynamic typing) but I have grown to appreciate its object orientation, closures and functional programming. Also, its global objects and removal of silent type conversion were a breath of fresh air when I first found them.

My preferred ide for javascript is webstorm as it is easy to get jQuery intellitext working (shame its not free).

Also, I wouldn't say its growing - its ubiquitous already.

Your specific points:

No immediate way of finding a function's entry point

I don't understand this, how could it be any simpler ?

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter

If you set up your ide to include the objects definition the properties of the object will be available via intellitext (but i may have missed your point here).

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

Common usage ? If you don't like anonymous functions, don't use them. Or are you referring to jQuery which uses them substantially ? jQuery is probably regarded by most web developers as the single biggest time saver in the history of web development.

JSLint catches some errors before runtime

It catches all of them, you can include it into your ide. Or Webstorm includes it by default (i think).


答:
If you like IDEs and are used to eclipse check out Aptana as an IDE For JavaScript. I think it can do much of what you want. (I personally hate IDEs but that is a different conversation).

As for anonymous functions, I find that they are the most powerful feature in JavaScript and trying to work in a language that does not have them is at this point quite painful.

If you want something else that can compile to JavaScript there are a bunch of options, CofffeeScript, Clojure and GWT all jump to mind but there are others.

Title: How does a programmer used to static languages cope with lack of Javascript tooling

Body:
I have programmed pretty much exclusively in compiled languages, particularly Java, for most of my career.  One of my favourite things about Java is how productive you can be, and how little code you actually have to write, when using tools like Eclipse.

You can:

Easily and automatically refactor your methods and classes

View instantly all the places where a method is invoked, or a constant is used (Open Call Hierarchy/Show References)

Static typing means you can use code completion to show all the parameters/functions available on an object

Control-click on a function/member/class name to go straight to its definition

All these facilities make me feel like the IDE is my best friend.  Writing Java code and particularly understanding other peoples' programs becomes far easier.

However, I am being called on more and more to use Javascript, and my experience so far has been quite negative.

In particular:

No immediate way of finding a function's entry point
(other than a plain text search, which may then result in a subsequent searches for methods further up the call hierarchy, after two or three of which you've forgotten where you started)

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter
(other than actually running the program, navigating to the point at which the function is called, and using console.logs to output all the properties available)

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

The upshot is that you pretty much need to have the entire program in your head at all times.  This massively increases the cognitive load for writing complex programs.  And all this extra stuff to worry about leaves less room in my brain for actual creativity and problem solving.

Sure, it's faster to just throw an object together rather than write an entire formal class definition.  But while programs may be slightly easier and quicker to write, in my experience they are far harder to read and debug.

My question is, how do other programmers cope with these issues?  Javascript is clearly growing in popularity, and the blogs I read are about how productive people are being with it, rather than desperately trying to find solutions to these issues.

GWT allows you to write code for a Javascript environment in Java instead, but doesn't seem to be as widely used as I would expect; people actually seem to prefer Javascript for complex programs.

What am I missing?


答:
That's the price we pay for using poorly typed languages. One can only wonder why this abomination has become so popular. The disadvantages far outweigh the advantages of poorly typed languages.

Perhaps we should apply the Non-cooperation-principle to this junk to make it go away.


问:
Should I tell someone that their commit caused a regression?
When you track down and fix a regression—i.e. a bug that caused previously working code to stop working—version control makes it entirely possible to look up who committed the change that broke it.

Is it worth doing this? Is it constructive to point this out to the person that made the commit? Does the nature of the mistake (on the scale of simple inattentiveness to fundamental misunderstanding of the code they changed) change whether or not it's a good idea?

If it is a good idea to tell them, what are good ways to do it without causing offense or causing them to get defensive?

Assume, for the sake of argument, that the bug is sufficiently subtle that the CI server's automated tests can't pick it up.

答:
Always regard the other person as someone better than you , always see others good characteristics and always know that I can make mistakes too.

Tell them when its only the two of you.


答:
What you're saying is just the common gripe of a Java minded person looking at JavaScript.

Let's first answer your question...

... my question is, how do other programmers cope with these issues ...

Answer: They DON'T. They learn the JavaScript philosophy by first relinquishing the Java cult.

You have to understand this premise... JavaScript is NOT Java.
It's just not about syntax -- it's more about the philosophy.

Now let's take up some of them...

View instantly all the places where a method is invoked, or a constant is used (Open Call Hierarchy/Show References)

Control-click on a function/member/class name to go straight to its definition

All of these are available -- just pick a decent IDE.

Static typing means you can use code completion to show all the parameters/functions available on an object

This is not a problem you cope with. This is something that requires changing your outlook on programming. Loose type system is one of the strengths of JavaScript. Understand loose typing -- and learn to appreciate it. Besides, code completion works very well with JS.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

Firebug, Chrome/Safari console and even IDEs do all that and MORE.

There is JSHint that can do the nifty static analysis that Java programmers are used to.

The upshot is that you pretty much need to have the entire program in your head at all times. This massively increases the cognitive load for writing complex programs.

Wrong! On the contrary, JavaScript is a "lightweight" programming language -- and encourages you to have simpler programs. As Doug Crockford says ... it will "punish" you if you tried to write heavily model based programs in JavaScript.

while programs may be slightly easier and quicker to write, in my experience they are far harder to read and debug.

Totally wrong! How do you decide readability based on programming language? Programs are readable (or not) -- NOT languages. Plus, JavaScript's got fantastic debuggers.

Pardon me if I sounded a little rude -- but the truth is you have to change your Java disposition to understand JavaScript.

Only "mature" Java programmers can appreciate JavaScript -- and you can't master that which you don't appreciate. Again, sorry for being outright blunt.