问:
Dependency Inversion Principle vs "Program to an interface, not an implementation"
I'm trying to understand how the Dependency Inversion Principle differs from the "program to an interface, not an implementation" principle.

I understand what "Program to an interface, not an implementation" means. I also understand how it allows for more flexible and maintainable designs.

But I don't understand how the Dependency Inversion Principle is different from the "Program to an interface, not an implementation" principle.

I read about DIP in several places on the web, and it didn't clear up my confusion. I still don't see how the two principles differ from each other. Thanks for your help.

答:
Interfaces are one way to implement DI.  If you specify an interface as a parameter in the constructor method of a class, you can hand any object you like to that constructor method, so long as that object implements the interface of the constructor parameter.

In other words, programming an interface allows you to  change the implementation of that interface. It's how we are able to substitute mock objects for real objects during unit testing, specify different data providers, and so forth.


问:
Dealing with co-workers who do not have a consistent coding style?
What do you when you're working with someone who tends to write stylistically bad code? The code I'm talking about is usually technically correct, reasonably structured, and may even be algorithmically elegant, but it just looks ugly. We've got:

Mixture of different naming conventions and titles (underscore_style and camelCase and UpperCamel and CAPS all applied more or less at random to different variables in the same function)

Bizarre and inconsistent spacing, e.g. Functioncall  (arg1 ,arg2,arg3 );

Lots of misspelled words in comments and variable names

We have a good code review system where I work, so we do get to look over and fix the worst stuff. However, it feels really petty to send a code review that consists of 50 lines of "Add a space here. Spell 'itarator' correctly. Change this capitalization. etc."

How would you encourage this person to be more careful and consistent with these kinds of details?

答:
I think you just have to keep doing what you are doing.  Have a clear set of coding guidelines, and enforce them during code reviews.  If a developer gets 50 or 100 lines of "Add a space here" and "Spell 'iterator' correctly" every time he tries to check something in, and he is actually not allowed to check in before all of those get fixed, eventually he'll have to start writing cleaner code just to avoid the hassle.

I think if you fix these things yourself, like NimChimpsky suggested, you will be cleaning up after this person forever.

ContentLicense: CC BY-SA 2.5


答:
"Program to an interface" means don't depend on a concrete type to do your work, but it doesn't specify how you should get your dependency.

The "Dependency Inversion Principle" says that an object shouldn't control the creation of its dependencies, it should just advertise what dependency it needs and let the caller provide it. But it doesn't specify whether the dependency should be a concrete type or an interface.

I'll illustrate the differences with some C# code.

The following example depends on a concrete type, and it controls it's own dependency's creation. It follows neither "program to an interface" nor "dependency inversion":

```<code>public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor()
    {
        _myThing = new MyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}
</code>```

The following example depends on an interface, but it controls it's own dependency's creation. It follows "program to an interface", but not "dependency inversion":

```<code>public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor()
    {
        _myThing = ThingFactory.GiveMeANewMyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}
</code>```

The following example depends on a concrete type, but it asks for its dependency to be created and passed to it. It follows "dependency inversion", but not "program to an interface":

```<code>public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor(MyThing myThing)
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}
</code>```

The following example depends on an interface, and it asks for its dependency to be created and passed to it. It follows both "dependency inversion" and "program to an interface":

```<code>public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor(IMyThing myThing) // using an interface
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}
</code>```

ContentLicense: CC BY-SA 3.0

Title: Dependency Inversion Principle vs "Program to an interface, not an implementation"

Body:
I'm trying to understand how the Dependency Inversion Principle differs from the "program to an interface, not an implementation" principle.

I understand what "Program to an interface, not an implementation" means. I also understand how it allows for more flexible and maintainable designs.

But I don't understand how the Dependency Inversion Principle is different from the "Program to an interface, not an implementation" principle.

I read about DIP in several places on the web, and it didn't clear up my confusion. I still don't see how the two principles differ from each other. Thanks for your help.

Body:
"Program to an interface" means don't depend on a concrete type to do your work, but it doesn't specify how you should get your dependency.

The "Dependency Inversion Principle" says that an object shouldn't control the creation of its dependencies, it should just advertise what dependency it needs and let the caller provide it. But it doesn't specify whether the dependency should be a concrete type or an interface.

I'll illustrate the differences with some C# code.

The following example depends on a concrete type, and it controls it's own dependency's creation. It follows neither "program to an interface" nor "dependency inversion":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor()
    {
        _myThing = new MyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

The following example depends on an interface, but it controls it's own dependency's creation. It follows "program to an interface", but not "dependency inversion":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor()
    {
        _myThing = ThingFactory.GiveMeANewMyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

The following example depends on a concrete type, but it asks for its dependency to be created and passed to it. It follows "dependency inversion", but not "program to an interface":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor(MyThing myThing)
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

The following example depends on an interface, and it asks for its dependency to be created and passed to it. It follows both "dependency inversion" and "program to an interface":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor(IMyThing myThing) // using an interface
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}


问:
Is it fine for a class that creates objects to delegate them?
I have a large list of intercommunicating components; so I decided to have one class create all of them and then subsequently delegate them to other classes to facilitate finer tweaking and wiring together.

By "finer tweaking", I mean that the components are modified to their final state; and by "wiring together" I mean that components are given a way to communicate in a specific manner.

After they are all wired together, I send all the components over to an organizer to be properly organized into a GUI.

I read somewhere that a class should only create objects or use them, but never both; so, I am trying to follow that and also limit each class's responsibilities.  This initializer/delegator class does both initializing and delegating, so should I further split it into an initializer and delegator?

答:
Your top level class that does this creating and delegating sounds like a Service Locator, or Dependency Container. A Service Locator receives requests from components for objects providing a particular service (that is, implementing a particular interface).  It goes off and creates an object of the relevant type (or gets an instance out of its cache depending on how exactly its been configured to handle requests for such services) and passes it back to the caller.

If your top level class is the first thing that's called in your application, then it may be a Bootstrapper.

In the former case, the delegation is implicit because you're calling into the Service Locator and returning the particular services, so all your class should be doing is creating instances of the relevant types at the appropriate times.

In the latter case, it's OK, because a Bootstrapper's task is to initialise the global data structures and spin up the processes that will operate on them.


问:
Observer pattern: "Web of observers" - Is this ever in use?
I had an idea (which I'm sure already exists), to create a sort of 'network of observers/subjects'. I would like to describe how it works and than ask several questions about it.

Say we have 5 objects: Objects A, B, C, D and E. Objects D and E need to observe objects A, B and C.

With the regular Observer pattern, both D and E would register as observers to A, B and C. This means both D and E would have to register three times as observers, creating six observer-subject relationships total.

The idea is to add another object in the middle, let's call it Object O. It implements both the Observer and Observable interfaces. It registers as an observer to objects A, B and C. Objects D and E register as observers to object O.

Whenever objects A, B and C notify object O, object O notifies it's own observers - D and E. Thus creating a sort of network. This network has a total of five observer-subject relationships.

As I see it, this has two main benefits:

The less important benefit: This solution allows for less observer-subject relationships, and thus (I think) creates less complexilty in the system. In this simple description the number of relationships only gets reduced by one, but the more observers and subjects there are, the bigger the benefit.

The more important benefit: Please consider an application with two groups of objects, group A and group B. All objects in group A need to observe all objects in group B. If we decide to add an object to group B, than using regular Observer we'd have to update a lot of code to register all objects in group A as observers to the new object. With the 'network' solution (which I'm sure has a different name), we only register the 'middle' object (object O) as an observer to the new object in group B, and all objects in group A would be notified when the new object in group B changes state.

My questions:

Is this solution ever in use in professional projects? Did you ever encounter this in use? Or is it just a cool idea but never used in practice?

What would you say are this pattern's disadvantages?

Does it have more advantages that I'm not aware of?

Does this have a name?

答:
Sure, these things exist. D-BUS comes to mind, or any number of messaging frameworks (RabbitMQ , AMQP, ZeroMQ, etc). They're all variations on a similar theme.

Increased latency compared to directly-connected peers, and increased complexity for complex topologies.

The biggest one I can think of is the ability to extend to multiple WANs and scale to massive numbers of subscribers. (Search for 'message queue federation' to learn more). Also, service discovery. Clients only need to know about the 'router' component in the middle to connect to any service.

There are so many variations that it's hard to pick a single name, but I would call it a 'software message bus' or 'message broker'.


问:
Are there any cases when one should not use Test Driven Development?
Is it recommended that TDD be always practiced in a project, or are there cases when it should be avoided?

Should we all adopt TDD?

Is it standard practice in major software companies?

答:
I think it all comes down to a simple question: Does it have to work?
If it does, then I would say it is best to do TDD, on the majority of cases.

To me, the exceptions are very lightweight pieces of code.
Weight the effort of manually testing every single procedural branch in the code. If this effort is smaller than that of writing automated tests, then I'd say it wouldn't be a problem to not do TDD. By the way, if you have to run the manual tests more than once, that effort is multiplied.

So, if we think about it, there's hardly any useful kind of software to which the effort of manually testing (multiple times) would be lower than writing automated tests. I can only  think of small proof-of-concepts and demonstration code, but even then I'd prefer to practice TDD, because such prototypical code may grow to become full functioning software.

Now, as for TDD as official practice in major companies, I can only answer based on the company I work for, and no, it isn't. There are companies that require unit tests to be written by the end of an iteration, with an "acceptable" range of code coverage, but that is completely different to practicing TDD.

In any case, we, as software developers, professionals, have to decide whether or not to practice TDD, not our contractors.


问:
PHP coding practice
I'm a self taught PHP programmer. Because I have no formal training in PHP, I often find my coding style to be considerably different than example code I find on the Internet. I've slowly started adapting some of the more common practices I find. However, before changing my habits, I try to find a good reason to use the new style. I just don't see much reason to change my habit if it isn't actually advantageous.

I see a lot of people write PHP code such as :

```<code><h1><?php echo $cTitle; ?></h1>
<div><?php print $cContent; ?></div>
</code>```

Whereas I generally write :

```<code><?php
    echo "<h1>", $cTitle, "</h1>";
    print("<div>" . $cContent . "</div>");
</code>```

What I'm seeing is that people are commonly going in-and-out of PHP, while I'll just use PHP to print/echo the html content along with the PHP variables.

Is there a measurable difference between these two methods? Is there a good reason for me to change my ways?

答:
The reason you see a lot of html templating is probably because of an "appearence driven" workflow.

I.E. You start by coding up an HTML page that "looks right" then add in the dynamic php elements later.

This works well if you also follow a classic Model View Controller pattern -- essentially you do all your business logic in php before invoking the template which should have minimal php code consisting mostly of simple substitution of previously calculated values.

Title: PHP coding practice


问:
Why are SW engineering interviews disproportionately difficult (vs. research interviews)?
First, some background on me. I have a PhD in CS and have had jobs both as a software engineer and as an R&D research scientist, both at Very Large Corporations You Know Very Well. I recently changed jobs and interviewed for both types of positions (as I have done in the past).

My observation: SW engineer job interviews are way, way disproportionately more difficult than CS researcher job interviews, but the researcher job is higher paying, more competitive, more rewarding, more interesting, and has a higher upside.

Here's a typical interview loop for researcher:

Phone interview to see if my research is in alignment with the lab's research

In-person: give presentation on my recent research for one hour (which represents maybe 9 month's worth of work) and answer questions from the audience

In-person one-on-one interviews with about 5 researchers, where they ask me very reasonable questions on my work/publications/patents, including: technical questions, where my work fits into related work, and how I can extend my work to new areas

Here's a typical interview loop for SW engineer:

Phone interview where I'm asked algorithm questions and maybe do some coding. Pretty standard.

In-person interviews at the whiteboard where they drill the F*** out of you on esoteric C++ minutia (e.g. how does a polymorphic virtual function call work), algorithms (make all-pairs-shortest-path algorithm work for 1B vertices), system design (design a database load balancer), etc. This goes on for six or seven interviews. Ridiculous.

Why would anyone be willing to put up with this? What is the point of asking about C++ trivia or writing code to prove yourself? Why not make the SE interview more like the researcher interview where you give a talk about what you've done?

How are technical job interviews for other fields, like physics, chemistry, civil engineering, mechanical engineering?

答:
I am a software developer (c/c++) with over 20 years in the field.  The type of interviews we routinely see now (the brain teasers, implementing data structures, search algorithms etc. on the whiteboard) didn't used to occur much except for newgrads.   If a person worked for a reputable company for reasonable amount of time, that was considered proof of one's ability to write code.  Now its become very schoolish and I'm not sure why.  Really, the typical things they ask you to code, CAN be memorized so doing it on the whiteboard really does not prove anything.  On a work project, you'd use the internet to research something and you would not be writing btrees or linked lists from scratch.  What companies truely need now are innovators and asking someone to prove they can write from memory structures from college does not demonstrate innovation.

I think its another management fad - just like scrum - with this one probably being started by google, amazon and microsoft.  Everyone else copied just like they did with Jack Welch's rank and yank...remember GE?

If you are a hiring manager reading my comments, what you SHOULD be asking candidates is HOW they would go about solving certain problems.  Instead of asking them to code a hash table, give them a problem involving a hash table and ask how they would solve it.

I also agree with the developer above this post who said "give them a real world problem that the company had to solve"!

"but I'd tend to bomb the OOP/Inheritance questions. Why? Because once support for templates was added, I've used C++ almost exclusively for Generic Programming."

I also agree with the above.  When you work for a company, you write code THEIR way.  I still struggle sometimes to remember C++ call by reference syntax off the top of my head because the senior architect at the company I worked 15 years for, prefered to use pointers, not references.  He was an old C programmer you see.   So thats what we all used.


问:
What would you add in this Software Development Project Checklist?
I'm a big fan of checklists. There is Travel Checklist, Moving Checklist and even a Scrum Checklist.

Context: you have been hired by a large corporation and given the mission to setup the whole software development environment, processes, team, etc. You have "carte blanche". You will be responsible for the creation of the working increments of the software. Project size: 2000 man/days.

What items would you add to the following (intentionally small and incomplete) checklist:

Install a Continuous Integration Server

Write a DoD

Write a one page coding guidelines

Create a product backlog

Install a Bug Tracking System

Schedule Regular Face Time

答:
Some things I don't see in the question and subsequent answers:

Disaster Recovery Plan. How are you backing up the dev boxes, staging, testing etc? Does every dev have what they need to work from home on the occasional snow day? Etc.

Training Plan. How many weeks of year of training do your devs need to keep sharp? Is anyone tracking it? (A spreadheet can suffice for most teams.) Have a mechanism for them to report (sending someone an email saying they watched 2 hours of webcasts on "whatever" is probably enough) and for management to plan - eg who should we send to what conference this year.

a Tool Position. Is this a "we give you all an MSDN subscription; please don't install anything else on your work machines" kind of place or a "we want your code but we don't care what you use to edit, compile and test it" kind of place. Make and record the decision.

as much integrated ALM as you can stand or afford. Usually the reason for the "impedance mismatch", double entry, tool overlap, and swivel chair application integration is that the system grew by bits and pieces. Starting from scratch, you want to show that your people can stay in a single tool throughout the cycle. Not typing code in X, compiling with Y, testing with Z, changing the status of the work item / task with A, reporting their time spent with B, telling the person who was waiting that they can now proceed with C, trying to figure out what to do next with D, guauging overall progress with E, etc.


答:
Factors Limiting Industrial Adoption of Test Driven Development, a research paper from 2011, reviewed 9,462 papers on TDD, and included 48 studies as a basis for their research. The paper covers the topic of why TDD may not be used in depth, but for ease of reference, here's a summary:

Development time: Development time could be considered a business-critical factor for adopting new practices within an
  organization. Depending on the maturity of the organization, an
  up-front loss (in this case, increased development time) might
  overshadow a long-term gain (e.g., decreased overall project time, or
  increased product quality – both of which were reported in many of our
  included studies). Hence, internal organizational pressure might risk
  the proper usage of TDD.

Experience/knowledge: When observing collected data from the included primary studies, we noticed that participants in the
  experiments (either students or professionals) were mostly provided
  with some training or tutorial on how to perform TDD. In several
  cases, the knowledge improved as participants would progress with the
  experiment. We expect that lack of knowledge or experience with TDD
  could create problems in its adoption.

Design: There is no massive empirical support that the lack of design should be considered as a limiting factor for industrial
  adoption of TDD. However, there are a handful of studies reporting
  problems regarding lack of design in TDD, particularly in the
  development of larger, more complex systems. Moreover, the lack of
  upfront design has been one of the main criticisms of TDD since its
  introduction and even if the evidence supporting this criticism is
  sparse, so is the evidence contradicting it.

Skill in testing: Since TDD is a design technique where the developer undertakes development by first creating testcases and then
  writes code that makes the test cases pass, it relies on the ability
  of the developer to produce sufficiently good test cases.
  Additionally, one study reports on the risk it brings to adopt TDD
  without having adequate testing skills and knowledge. We find it
  interesting that there are no explicit investigations of the quality
  of test cases produced by developers in TDD.

TDD adherence: The combined view of five industrial case studies state that the inclusion of the lack of TDD adherence as a
  limiting factor. Basically, the studies state that (1) it is important
  to adhere to the TDD protocol, and (2) developers do stray from the
  protocol in several situations. It is however far from certain that
  there is a clean-cut cause-effect relationship between low TDD
  adherence and low quality. Not unlikely, confounding factors (e.g.,
  tight development deadlines) might lead to both low TDD adherence and
  poor quality

Domain and tool specific issues: Proper tool support for test automation is vital for the successful adoption of TDD. With the wide
  variety of studies reporting domain- and tool-specific issues as a
  limiting factor in the adoption of TDD, the factor would be difficult
  to ignore.

Legacy code: TDD, in its original form, does not discuss how to handle legacy code. Instead, the method seems to assume that all code
  is developed from scratch, using TDD as the development method. As
  this is seldom the case in large development organization, adoption of
  TDD might be problematic. A lack of automated regression suites for
  legacy code hampers the flexibility provided by the quick feedback on
  changes provided by the regression suites, and may leave developers
  more anxious about how new changes may unexpectedly affect existing
  code.

Title: Are there any cases when one should not use Test Driven Development?

Body:
Is it recommended that TDD be always practiced in a project, or are there cases when it should be avoided?

Should we all adopt TDD?

Is it standard practice in major software companies?


答:
Some cases I can think of when one might not want to to TDD are:

minor changes to old systems that have no tests.

minor changes to old systems that have no test framework.

design and development of visual items and effects.

tight deadlines and a disinclination to produce quality work.


问:
The place of UI design when estimating and elaborating user stories
Our company is trying to follow Agile methodologies when it comes to estimating and prioritizing any new development work.  The reading I've done makes this concept appear great so we are trying to give it a good crack at making it work for us and hence help with providing a better solution at the end of the day for our customer.

A problem I have had recently is the position of UI design during the estimation of User stories.  We kicked off a new project discussing what was required from a functional point of view and getting a set of user stories written down to be verified by the user.  Our BA then asked us to estimate these stories.

I went, hang on.  Many of these stories might vary depending on the complexity of the UI design.  However the BA wasn't ready to discuss UI just yet as she needed estimates so she could plan the sprints and get a costing for the project.

So my main question is:

Where does UI design fit into the process between writing user stories
  and estimation.  Or, should it even fit in and just be a part of the
  development work?

Secondary question

How does agile fit into fixed price quotes for new work (based on your
  estimations on the entire user stories set), and how then do you
  ensure you deliver what you said as far as the user stories go against
  the quote given i.e. a story is bigger than you thought so blows out

My concerns around our process:

I can't estimate accurately enough at this stage of the process as some elements are missing i.e. UI. It's a new project for a new client so heading into some uncertain waters.

Some features are just too unknown to estimate  (Do I need to just delve deeper into the murkiness to clear the waters to remove the unknowns??)

BA needs (as expressed to me)

Wants to have estimates so they can determine how many sprints this project will take

Wants to have estimates so they can determine the scope and cost of the project so that they can give it to the customer as a quote.

答:
UI design is no different than architecture or coding or testing -- it's part of the scrum process. Some say that in an ideal world the team will do all of that in a sprint -- but only enough UI design for that sprint. Others are more pragmatic and say it can't be done, and will do design in one sprint and coding and testing in another, or design and coding in one and testing in another.

A common pattern is to do design work / UI stories in one sprint and code in the next. After all, if you don't know what the UI is like there's no way you can estimate how much effort will be involved in coding. Consider the difference in the home page for google.com vs bing.com -- both have the same primary function, but bing.com has a considerably more elaborate UI design.

That being said, estimates are just that: estimates. Nothing in scrum requires that they are accurate only that they are consistent over time. Whether you estimate a story as a 5 or a 13 doesn't matter as long as similar stories are estimated the same way from sprint to sprint.

So, do what the team thinks is right -- do a UI story before doing the development, or do them together. If the PO says they have to be done at the same time, make sure you factor into your estimates all of the uncertainty. Do your best to estimate, knowing it will be wrong. Learn from that in your retrospective and talk about what worked and what didn't. Then, adjust your procedures going forward.

Above all, don't expect the estimates for the first half-dozen sprints or so to be the least bit accurate. Over time, however, regardless of the strategy you should start to do approximately the same number of points each sprint, which the PO can then use to predict how many stories you can do in a sprint.


问:
Not assigning Bugs to a specific user
My question: Is there a benefit to NOT assigning a Bug to a particular developer? Leaving it to the team as-a-whole?

Our department has decided to be more Agile by not assigning Bugs/Defects to individuals. Using Team Foundation Server 2012, we'll place all Bugs in a development team's "Area" but leave the "Assigned To" field blank.
The idea is that the team will create a Task work item which will be assigned to an individual and the Task will link to the Bug. The Team as a whole will therefore take responsibility for the Bug, not an individual, aligning to Scrum - apparently.

I see the down side. The reporting tools built into TFS become less useful when you cannot sort by assigned vs unassigned, let alone sorting by which user Bugs are assigned.

Is there a benefit I'm not seeing? Besides encouraging teamwork by putting the responsibility on the team-as-a-whole instead of an individual?

答:
I try not to think of the assignment of a User Story or Bug as assigning sole responsibility to one developer.  Try to think of it as assigning someone who is responsible for driving the effort required to resolve it.  Anyone can be pulled in as necessary and could be potentially assigned a task to capture that effort. </p>

<p>For larger teams that use Area Paths driven by sub-teams, you can leave a Bug or User Story unassigned but attached to a team-based Area Path. </p>

Title: Not assigning Bugs to a specific user

Body:
I try not to think of the assignment of a User Story or Bug as assigning sole responsibility to one developer.  Try to think of it as assigning someone who is responsible for driving the effort required to resolve it.  Anyone can be pulled in as necessary and could be potentially assigned a task to capture that effort.

For larger teams that use Area Paths driven by sub-teams, you can leave a Bug or User Story unassigned but attached to a team-based Area Path.


问:
Why can't a User Story be attached to more than one Feature?
I'm using Features to document the features as we originally communicated them to our client at proposal stage. I now want to create User Stories that relate to the features so that I can  easily map our stories back to the proposal.

Many of the stories naturally map across features, but Team Foundation Server (TFS) doesn't let me give a Story more than one Parent feature. Is this because I'm "doing it wrong" or is it more a limitation of TFS at the moment?

答:
In the TFS parent/child relationship a work item can only have one parent.  However, a parent can have multiple children.

From an Agile process perspective, a user story should only ever align to one feature.  I would suspect that either your features or your user stories are poorly-defined.  Perhaps your user story is too large or is system-oriented as opposed to user-oriented.  On the other hand, perhaps your features are too granular and should really be user stories tying into a feature at a higher level.   Would you be able to give an example of a user story that would attach to multiple features?

A feature should be a high-level functionality with a collection of user stories scoping out how the users of your software will interact with that functionality.  For example, "Login Functionality" could be a feature.  "Implement Facebook Authentication", "Implement Account Deletion", and "Implement Password Reset" would all be user stories that tie into that feature.


答:
Agree on a coding convention

Even if this is a one pager. I suggest that the whole team sit down and all agree on basic working coding convention that the whole team can use.

Title: Dealing with co-workers who do not have a consistent coding style?

Body:
What do you when you're working with someone who tends to write stylistically bad code? The code I'm talking about is usually technically correct, reasonably structured, and may even be algorithmically elegant, but it just looks ugly. We've got:

Mixture of different naming conventions and titles (underscore_style and camelCase and UpperCamel and CAPS all applied more or less at random to different variables in the same function)

Bizarre and inconsistent spacing, e.g. Functioncall  (arg1 ,arg2,arg3 );

Lots of misspelled words in comments and variable names

We have a good code review system where I work, so we do get to look over and fix the worst stuff. However, it feels really petty to send a code review that consists of 50 lines of "Add a space here. Spell 'itarator' correctly. Change this capitalization. etc."

How would you encourage this person to be more careful and consistent with these kinds of details?


问:
Does functional programming add complexity in code?
For the entire past year I've been written Scala code (coming from a Java background). I really liked how you could create simpler and cleaner code, with vals, case classes, map/filter/lambda functions, implicits and the type inference. I've used it mostly for an Akka-based application.

This year I'm on a Scala project with a new team, who really like functional programming. They heavily use Scalaz, and the code is filled everywhere with applicatives, context bounds, reader/writer/state monad, even the main method is "wrapped" in an I/O monad. Their reasoning is that this makes the compiler "work for us" in asserting that the code is correct, and each function is free from side effects.

Even so, from my point of view all this syntax really gets in the way of the business logic. For instance, a type of "MyBusinessObject" is fine, as well are types like "List[MyBusinessObject]", "Option[MyBusinessObject]" or even "Future[MyBusinessObject]". They all have a clear meaning and purpose. On the other hand, code like:

```<code>def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}
</code>```

does it add complexity to the program, or is it just me that I'm not used to this way of programming?

答:
This has nothing to do with functional programming - you can find this kind of situation in context of any other programming language - developers who love the advanced constructs of "their" language so much that they ignore any common sense about readability and keeping things simple. I have encountered such a situation in C, C++, Perl, Java, C#, Basic, and other non-functional languages. It's not functional programming that adds complexity to code - programmers do.

Don't get me wrong, I don't recommend avoiding advanced language features - but it's important to find the right balance in the given context. When writing a generic library for the usage of >100,000 developers all over the world, there are different measures to apply as when you are writing an individual report generator just for your local office.


问:
If TDD is design, how do you know your TDD is well designed?
Given a large group (50+) of programmers:

All given the same problem,

All using Test-Driven Development (TDD),

All pair programming,

All doing group-based code review,

I have personally seen the wide spectrum tests that are possible for the same problem, even on the first test. So, if TDD is design, how do you know your TDD is optimal for the current problem, and how do you know it is not? Following the first test, is the approach for reviewing the consecutive tests any different, and if so, how?

答:
TDD is not design - it is a design process.

A main artifact a TDD process eventually give you is the unit test suites, which should (to some degree) attest to the actual code's scope and capabilities.

Good test suites give some assurances that the code works, and added security that future code changes can be done without breaking past code, as failing tests will prevent broken code from leaking to the system.

So, if you want to evaluate a test suite written during TDD you should look for:

Readability

Tests should be easily read. It should be obvious what each test does.

A good test-suite describes the code functionality as a PRD (Product Requirement Documents) would, down to the edge-cases.

Tests that you can't understand what they do, are confusing, filled with 'magic numbers', long lines, illogical flow, vague objectives are bad. In a few weeks nobody will remember their purpose, and when they break, no one will no why or how to fix them, and they will be deleted from the code base, or worse yet - simply ignored, and left as broken tests in your code.

Succinctness

Individual tests should be short. They should test a single thing or use case.

When a good test fails, its name is sufficient to send the programmer to the correct class and method, maybe even line of code where he should look for the problem.

If a test is long, and has many moving parts - when it fails it just means now the programmer needs to first find out where the test failed, and the bug hunt, instead of being focused in the code, starts from combing the test itself.

Predictability

Tests should be deterministic.

When a good test fails, it fails every time.

Tests which are time bound (rely on Time.now()), statistical (use Random), or rely on external assumption (that a specific row is in a table, that a web service is available and working...) are not reliable, since they might pass when they should fail, or fail when they should pass, and eventually be ignored by the team.

Make sure a test stubs out all external dependencies (yes, Time and Random as well).

You can't test randomness!

I once saw a test which tested that an array shuffle does not return a sorted array - well, guess what - the sorted array is a valid random result!

Completeness

A good test suite is comprehensive.

When you read through a test suite, try to think of all the edge-cases, and see if they are tested.

Poor test suites fail to cover non-mainstream use-cases, and allow functional bugs to exist in a code which passes them.

DRYness

A good test suite should be DRY.

This helps both readability and maintainability. As the code base evolves, so are the tests.

If changes to tests involve cumbersome search and replace, and hours of programmer time to make failing tests pass (by updating the tests) each time the requirements change, it will make the whole approach fail, as programmers will simply stop maintaining the tests, and abandon TDD altogether as "too time consuming".

Good tests, when DRY, are easier to maintain, as code changes should involve less changes in the tests, and hence less time spent in old test code.

Speed

A good test suite should not take more than a few seconds to run.

The longer a test suite takes to run, the less times it will be run.

I/O, especially networking, but also heavy disk reads/writes, complex DB queries, etc. should be faked or stubbed.

Never use sleep() in tests. Fake time instead.

Sometimes there are tests you have to do which take more time. Contain them in a special 'long running' section, perhaps in the "integration" test suite, and have them run less often (nightly perhaps).


答:
They are generally same thing. If you read What is the Dependency Inversion Principle and why is it important? and Dependency Inversion Principle, you will realize the two "principles" talk basically about the same thing.

High level modules should not depend upon low-level modules. Both should depend upon abstractions.

Abstractions should never depend upon details. Details should depend upon abstractions.

Interface is an abstraction and implementation is a detail. If you substitute them in previous two statements, you get basically "code should depend on interfaces and not implementations". And that sounds as same thing to me.


答: Sounds like you need to set up and agree to a style convention.  If you don't you'll have libraries that have 3 space indents, others that have 4, some that use Camel Case and other that use underscore_case.</p>


答:
I would say that you not being accustomed to the way they code is at least part of the picture. I'm in a similar situation as you (coming from C# into F# and working with people with Haskell background), and while I find it an interesting experience, I do have moments when I'm banging my head against the wall, untangling a particularly convoluted point-free function composition just to get a hang of what's going on there. It's a cultural thing.

As for whether this particular code adds complexity to the program - I don't know. Agreed that a generic piece of code can be complex itself. But it's a utility, not a part of business logic. If you want to know whether it makes the codebase more complex or simpler, you would have to imagine how it would have to look without that piece of code. It's often the case with such generic constructs that they're complex themselves, but it's a complexity that you can fit on a single screen. In the same time they make the entire codebase a fair bit simpler. This particularly is the case with monads.

Then again, it also can be a case of 'art for art's sake', like @Doc Brown suggests. Can't rule it out either.

Title: Does functional programming add complexity in code?

Body:
For the entire past year I've been written Scala code (coming from a Java background). I really liked how you could create simpler and cleaner code, with vals, case classes, map/filter/lambda functions, implicits and the type inference. I've used it mostly for an Akka-based application.

This year I'm on a Scala project with a new team, who really like functional programming. They heavily use Scalaz, and the code is filled everywhere with applicatives, context bounds, reader/writer/state monad, even the main method is "wrapped" in an I/O monad. Their reasoning is that this makes the compiler "work for us" in asserting that the code is correct, and each function is free from side effects.

Even so, from my point of view all this syntax really gets in the way of the business logic. For instance, a type of "MyBusinessObject" is fine, as well are types like "List[MyBusinessObject]", "Option[MyBusinessObject]" or even "Future[MyBusinessObject]". They all have a clear meaning and purpose. On the other hand, code like:

```<code>def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}
</code>```

does it add complexity to the program, or is it just me that I'm not used to this way of programming?


答:
TDD shouldn't be used when some alternative approach is more appropriate. The key thing to remember is that the alternative approaches aren't so much manual testing, as things like:

Write and review a detailed design document

Produce a complete design in a CASE tool, press the 'generate code' button.

Create a set of unit tested reusable components, assemble a solution from them

Express the problem in terms of mathematics, create a provably-correct solution

Define a custom language in which it is easy to express the solution

Write code that makes the monkey dance, hit refresh.

Automated testing being especially difficult for some reason is one factor that might guide the choice of design method. But it is far from the key factor; in fact several of the other approaches will end up doing as much, or more, automated testing than TDD.


问:
Why did javascript libraries like knockoutjs, backbonejs, and angularjs only come out in 2010?
Being a relatively new web-developer I am surprised that these libraries didn't exist before.  Is there a particular technical or historical reason that at around Sep 2010, a sudden development and interest in client-side javascript RIA applications and libraries?

http://www.google.com/insights/search/#q=backbonejs%2Cangularjs%2Cknockoutjs%2Cjquery%20tmpl&cmpt=q

答:
Mainstream Javascript engines added JIT (Just In Time) compiling around that time.  Mozilla added TraceMonkey to Firefox, Google added Crankshaft to v8 around that time as well.  John Resig mentioned TraceMonkey when it was just coming out.

These optimizing runtimes improved javascript performance in browsers by an order of magnitude.  Before then, javascript engines just weren't fast enough to do on the client side.  In particular, Angular's method of doing data-binding using dirty checking would have been unworkable in javascript engines before 2010.

It also helped that around that time HTML5 was really starting to come together, and the differences between browsers started to diminish. That made it easier to develop rich javascript applications without having to worry quite so much about adding workarounds for each different browser.


问:
What is the best way to learn how to develop drivers?
At some point in my career I would definitely like to get involved in some embedded programming.  I was thinking that starting out with developing some drivers would be a good place to develop my abilities in the regard.  I'm open to doing so on either windows or linux platform (eventually will want to probably attempt both).  What tools would you recommend that I look into to get me started on this project?  Any other resources that you have found to be helpful (i.e. books, websites, programs, etc)?  Any advice/recommendations? Thanks!</p>

答:
the following link gives a brief introduction about developing device drivers in windows platform
http://msdn.microsoft.com/en-us/library/windows/hardware/ff554690(v=vs.85).aspx

but before starting driver development you should have full knowledge about the hardware that your are interfacing with the computer.In embedded systems the main communication channel between two components is established with help of RX/TX ports(RX for receiving, TX for transmitting).This even holds true in case of hardware and a PC.Any hardware connected to PC will continuously communicate with each other.Consider if we send 01 to a computer from hardware.we can program a specific task in driver development.conversely if we want switch an LED in the hardware then we need write a program such that on extrapolating information from computer the hardware should switch the light on.

the above link describes this topic far better than me take a look at it.


问:
How Do You Determine Your Hourly Rate?
In pricing a service or product it is general practice to not merely charge for the effort spent and the costs involved + margin but from the value delivered down. As an independent consultant, how do you set the price of your work?

What is the process of determining your hourly rate as an independent software developer? If you have one, what is your hourly rate and how did you arrive at that figure?

What factors would you take into account.  Is the process of setting a hourly rate only based on balancing demand with supply so that supply (you and your time) doesn't get overwhelmed?

When are the good times to raise your rates?

Are there projects in which you have had to charge higher than other projects? If so, please cite examples.

Do you change your hourly rate based on what kind of development you are doing? (for example, .net programming more, and lesser for php programming)

Do you set hourly rates based on what type of business the client is? If so how?

If you know of any relevant articles or material on the topic of charging for programming services, please post the same.

答:
It's not me making my hourly rates, it's the market. In bad times (e.g. around 2005), I have to step down. In 1995-2000, the .com boom, Y2K and the euro conversions caused hourly rates to skyrocket. In 2005, I had to do a Job at 65% of what I had earned in 1998 (and that job was not in any way less sophisticated). Today, I earn a lot better, fortunately.

To make this a useful advice: Ask friends, relatives etc. who work in the same industry and area how much is currently the usual rate. That's the price you should ask for, most clients will accept it and only a few clients would pay more.

Title: How Do You Determine Your Hourly Rate?


答:
One thing I learned about dealing with legacy code which I did this for medium and big projects with > 1 million lines of code, it makes sense to use TDD here as well. But it is much harder to get your code there in tests.

Normally legacy code bases doen't have any tests in place so fixing a bug and writing a unit test for it is a good starting point to get some. But normally you have to refactor the code a little bit before you can write these tests.
There is a really good book out where you can learn a lot about TDD with legacy code ( breaking dependencies, how to write the first test and so on ) : http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052


问:
Are there more efficient ways to search for help/documentation than Google/SO/...?
Google sometimes come up with irrelevant links, not everything is available on SO, there are cases where the local documentation is also annoying to look through... Are there other efficient ways you use to search?</p>

答: One of the most useful pieces of advice I can give is to start using Google Bookmarks. These results will appear when you are searching Google. I really like how (unlike other bookmarking services) this is set and forget. The bookmark sharing could be improved however.</p>


问:
Trying to "combine" similar objects without doing a bazillion comparisons
In this database I have "accesses" - each access can have any number (usually less than 4, sometimes as many as 15) attributes. I also have "tickets" where N users are requesting M accesses, so I've got a sub-ticket table with the NxM "user access requests". Then for the sub-ticket, there is another table with the A attributes for that access (where "A" varies depending on the request).

So, for example, if I have two users requesting three accesses, and those accesses have 2, 3 and 4 attributes respectively, I have 1 ticket record, 6 sub-tickets records, and 18 sub ticket attribute records.

The problem is that I want to quickly group the sub-tickets together, so that when I display them I can find all the ones for one type of access, then all the ones of another type of access, and then the third type of access. I know, each type of access should have been given a unique id somehow, but they weren't, and now it's my burden. I only am allowed to "suggest" database changes, not insist on them.

Any suggestions?

答: After making some test data to show the problem, I've managed to convince the powers that be that since I know which "sub ticket attributes" belong to which "access" at ticket creation time, it would be better just to put a "access serial number" (asn) field into the sub ticket table so if I have N users and M accesses, I'll have N subtickets with asn "1", N with asn "2" and so on.</p>


问:
Case insensitive keywords in a language
We're trying to write a custom scripting language. There has been a suggestion to make the language forgiving by providing case insensitive keywords.

I personally do not like the idea, but there are few people in my team leaning towards it, saying it will make the end user happy! Examples of languages like FORTRAN, BASIC, SQL are given saying that these are case insensitive.

Is this a good idea?

答:
I can't believe that someone said "case sensitivity makes reading code easier".

It most certainly does not! I've looked over a colleague's shoulder at variables called Company and company (public variable Company, matched private variable company) and his choice of font and colour makes it incredibly difficult to tell the difference between the two - even when next to each other.

The correct statement should be "mixed case makes reading code easier". That's a much more obvious truth - e.g. variables called CompanyName and CompanyAddress rather than companyname. But no language I know of makes you only use lower case variable names.

The most insane convention I know of is the "uppercase public, lowercase private" one. It is just asking for trouble!

My take on errors is "better that something fail noisily and as soon as possible rather than quietly fail but appear to succeed". And there's no sooner than compile time.

If you mistakenly use a lower case variable when you meant to use the uppercase, it will often compile if you are referencing it within the same class. Thus, you can appear to succeed in both compile and run time but be subtly doing the wrong thing, and perhaps not detect it for a long time. When you do detect that there's something wrong

Far better to use a convention where the private variable hass a suffix - e.g. Company public variable, CompanyP private variable. Nobody is going to accidentally mix up the two, and they appear together in the intellisense.

This contrasts with an objection people have to Hungarian notation, where a prefixed private variable pCompany would not appear in a good place in the intellisesne.

This convention has all of the advantages of the dreadful upper/lower case convention and none of its drawbacks.

The fact that people feel the need to appeal to case sensitivity to distinguish between variables shows both a lack of imagination and a lack of common sense, in my opinion. Or, sadly, the human sheep like habit of following a convention because "that's the way it's always been done"

Make the things you work with clearly and obviously different to each other, even if they're related!!

Title: Case insensitive keywords in a language


问:
Container/Item pattern without `friend`
I have a class Container containing objects of type Item. They are different classes, and especially they have no common base class (e.g. a Container does not itself have a Container).:

```<code>class Container
{
    public ICollection<Item> Items { get { /* ... */ } }
}

class Item
{
    public Container Container { get { /* ... */ } }
}
</code>```

I’d like to enforce that each Item needs to have exactly one Container, and I’d like to make sure there never can be an inconsistent situation such that e.g. i.Container.Items.Contains(i) returns false.

This could be done by e.g. adding a method Container.AddItem that sets the Item’s Container property accordingly or by having a Item.SetContainer method that takes care of Container.Items.

Example:

```<code>class Item
{
    private Container container;
    public Container Container
    {
       get
       {
          return container;
       }
       set
       {
           if (container != null)
               container.Items.Remove(this);
           container = value;
           if (value != null)
               value.Items.Add(this);
       }
    }
}
</code>```

This could be easily done with the concept of a “friend”, but I’m using C# that does not have friends, and thus this example code won’t compile. However, it of course would compile if Container.Items had a public setter, but this again would allow inconsistencies: A “user” of the classes would need to know not to use the setter of Container.Items, but Item.Container instead.

After searching for quite some time, I feel there is no way to enforce this restriction that seems to be so trivial. (Using internal might be a work-around, but no solution.)

Is there an elegant way to enforce this one-container-per-item rule without the concept of “friend”?

答:
internal would be a fine solution here since container and item are inextricably linked, they're going to be part of the same assembly.

That said, this is a code smell.

Items should generally not know if they belong in a container, let alone being restrained to only one container. This is a coupling nightmare since items will then inevitably go back to their container to look for other items, tightening that relation. Then you get into "how do I inform this item that the peer it cared about has suddenly left the container?" Which makes the container then care about which items care about what other items and on down.

Title: Container/Item pattern without `friend`


问:
Why does Python use hash table to implement dict, but not Red-Black Tree?
Why does Python use hash table to implement dict,  but not Red-Black Tree?

What is the key? Performance?

答:
This is a general, non-Python-specific answer.

Algorithmic complexity comparison

```<code>       | Hash Table  |   Red-Black Tree    |
-------+-------------+---------------------+
Space  | O(n) : O(n) | O(n)     : O(n)     |
Insert | O(1) : O(n) | O(log n) : O(log n) |
Fetch  | O(1) : O(n) | O(log n) : O(log n) |
Delete | O(1) : O(n) | O(log n) : O(log n) |
       | avg  :worst | average  : worst    |
</code>```

The problem with hash tables is that hashes can collide. There are various mechanisms to resolve collisions, e.g. open addressing or separate chaining. The absolute worst case is that all keys have the same hash code, in which case a hash table will degrade into a linked list.

In all other cases, a hash table is a great data structure that's easy to implement and delivers good performance. A downside is that implementations that can quickly grow the table and redistribute their entries will likely waste nearly as much memory as is actually being used.

RB-Trees are self-balancing and do not change their algorithmic complexity in a worst case. However, they are more difficult to implement. Their average complexities are also worse than that of a hash table.

Restrictions on keys

All keys in a hash table must be hashable and comparable for equality among each other. This is especially easy for strings or integers, but is also fairly straightforward to extend to user-defined types. In some languages like Java these properties are guaranteed by definition.

Keys in an RB-Tree must have a total order: each key must be comparable with any other key, and the two keys must either compare smaller, greater, or equal. This ordering equality must be equivalent to semantic equality. This is straightforward for integers and other numbers, also fairly easy for strings (the order need only be consistent and not externally observable, so the order does not need to consider locales[1]), but difficult for other types that have no inherent order. It is absolutely impossible to have keys of different types unless some comparison between them is possible.

[1]: Actually, I'm wrong here. Two strings may not be byte-equal but still be equivalent according to the rules of some language. See e.g. Unicode normalizations for one example where two equal strings are encoded differently. Whether Unicode character composition matters for your hash key is something that a hash table implementation cannot know.

One might think that a cheap solution for RB-Tree keys would be to first test for equality, then compare identity (i.e. compare pointers). However, this ordering would not be transitive: If a == b and id(a) > id(c), then it must follow that id(b) > id(c) as well, which is not guaranteed here. So instead, we might use the hash code of keys as the lookup keys. Here, the ordering works correctly, but we might end up with multiple distinct keys with the same hash code, which will be assigned to the same node in the RB tree. To solve these hash collisions we can use separate chaining just like with hash tables, but this also inherits the worst case behaviour for hash tables – the worst of both worlds.

Other Aspects

I expect to a hash table to have better memory locality than a tree, because a hash table is essentially just an array.

Entries in both data structures have a fairly high overhead:

hash table: key, value, and next entry pointer in the case of separate chaining. Also storing the hash code can speed up resizing.

RB-tree: key, value, colour, left child pointer, right child pointer. Note that while colour is a single bit, alignment issues could mean you'd still be wasting enough space for nearly a whole pointer, or even nearly four pointers when only power-of-two sized memory blocks can be allocated. In any case, an RB-tree entry consumes more memory than a hash table entry.

Insertions and deletions in an RB-tree involve tree rotations. These aren't really costly, but do involve an overhead. In a hash, insertion and deletion are no more expensive than a simple access (although resizing a hash table upon insertion is an O(n) endeavour).

Hash tables are inherently mutable, whereas an RB-tree could also be implemented in an immutable fashion. However, this is rarely useful.

Body:
This is a general, non-Python-specific answer.

Algorithmic complexity comparison

       | Hash Table  |   Red-Black Tree    |
-------+-------------+---------------------+
Space  | O(n) : O(n) | O(n)     : O(n)     |
Insert | O(1) : O(n) | O(log n) : O(log n) |
Fetch  | O(1) : O(n) | O(log n) : O(log n) |
Delete | O(1) : O(n) | O(log n) : O(log n) |
       | avg  :worst | average  : worst    |

The problem with hash tables is that hashes can collide. There are various mechanisms to resolve collisions, e.g. open addressing or separate chaining. The absolute worst case is that all keys have the same hash code, in which case a hash table will degrade into a linked list.

In all other cases, a hash table is a great data structure that's easy to implement and delivers good performance. A downside is that implementations that can quickly grow the table and redistribute their entries will likely waste nearly as much memory as is actually being used.

RB-Trees are self-balancing and do not change their algorithmic complexity in a worst case. However, they are more difficult to implement. Their average complexities are also worse than that of a hash table.

Restrictions on keys

All keys in a hash table must be hashable and comparable for equality among each other. This is especially easy for strings or integers, but is also fairly straightforward to extend to user-defined types. In some languages like Java these properties are guaranteed by definition.

Keys in an RB-Tree must have a total order: each key must be comparable with any other key, and the two keys must either compare smaller, greater, or equal. This ordering equality must be equivalent to semantic equality. This is straightforward for integers and other numbers, also fairly easy for strings (the order need only be consistent and not externally observable, so the order does not need to consider locales[1]), but difficult for other types that have no inherent order. It is absolutely impossible to have keys of different types unless some comparison between them is possible.

[1]: Actually, I'm wrong here. Two strings may not be byte-equal but still be equivalent according to the rules of some language. See e.g. Unicode normalizations for one example where two equal strings are encoded differently. Whether Unicode character composition matters for your hash key is something that a hash table implementation cannot know.

One might think that a cheap solution for RB-Tree keys would be to first test for equality, then compare identity (i.e. compare pointers). However, this ordering would not be transitive: If a == b and id(a) > id(c), then it must follow that id(b) > id(c) as well, which is not guaranteed here. So instead, we might use the hash code of keys as the lookup keys. Here, the ordering works correctly, but we might end up with multiple distinct keys with the same hash code, which will be assigned to the same node in the RB tree. To solve these hash collisions we can use separate chaining just like with hash tables, but this also inherits the worst case behaviour for hash tables – the worst of both worlds.

Other Aspects

I expect to a hash table to have better memory locality than a tree, because a hash table is essentially just an array.

Entries in both data structures have a fairly high overhead:

hash table: key, value, and next entry pointer in the case of separate chaining. Also storing the hash code can speed up resizing.

RB-tree: key, value, colour, left child pointer, right child pointer. Note that while colour is a single bit, alignment issues could mean you'd still be wasting enough space for nearly a whole pointer, or even nearly four pointers when only power-of-two sized memory blocks can be allocated. In any case, an RB-tree entry consumes more memory than a hash table entry.

Insertions and deletions in an RB-tree involve tree rotations. These aren't really costly, but do involve an overhead. In a hash, insertion and deletion are no more expensive than a simple access (although resizing a hash table upon insertion is an O(n) endeavour).

Hash tables are inherently mutable, whereas an RB-tree could also be implemented in an immutable fashion. However, this is rarely useful.


答:
Does it add complexity to the program, or is it just that you're not used to this way of programming?

Why do you think these possibilities aren't the same thing?

Well written code can be read by people who aren't familiar with the specific programming language. Some languages (BASIC, Pascal, etc) can be read and understood by school-children who have never even seen any programming languages before.

If someone who has experience with other languages and experience with Scala (and who I assume has worked with Scalaz for at least a week and has colleagues to explain the trickier things) is still confused; then that's proof that it has added complexity.


答:
You could extract this to a separated service that has the only resposnsibility to track Container<->Item associoations. I think this is a very flexible solution.

```<code>class Container<T>
{
    private IItemAssociations associations;
    public Container(IItemAssociations a)
    {
        this.associations = a;
    }

    public void Add(T i)
    {
        if (!associations.IsAddedToAContainer(i))
        {
            DoAdd(i);
            associations.AddAssociation(this, i);
        }
        else
            HandleAlreadyAdded(i);
    }
}
</code>```

You can have a static constructor method that injects a global association object or use some other injection mechanism.

Title: Container/Item pattern without `friend`

Body:
I have a class Container containing objects of type Item. They are different classes, and especially they have no common base class (e.g. a Container does not itself have a Container).:

```<code>class Container
{
    public ICollection<Item> Items { get { /* ... */ } }
}

class Item
{
    public Container Container { get { /* ... */ } }
}
</code>```

I’d like to enforce that each Item needs to have exactly one Container, and I’d like to make sure there never can be an inconsistent situation such that e.g. i.Container.Items.Contains(i) returns false.

This could be done by e.g. adding a method Container.AddItem that sets the Item’s Container property accordingly or by having a Item.SetContainer method that takes care of Container.Items.

Example:

```<code>class Item
{
    private Container container;
    public Container Container
    {
       get
       {
          return container;
       }
       set
       {
           if (container != null)
               container.Items.Remove(this);
           container = value;
           if (value != null)
               value.Items.Add(this);
       }
    }
}
</code>```

This could be easily done with the concept of a “friend”, but I’m using C# that does not have friends, and thus this example code won’t compile. However, it of course would compile if Container.Items had a public setter, but this again would allow inconsistencies: A “user” of the classes would need to know not to use the setter of Container.Items, but Item.Container instead.

After searching for quite some time, I feel there is no way to enforce this restriction that seems to be so trivial. (Using internal might be a work-around, but no solution.)

Is there an elegant way to enforce this one-container-per-item rule without the concept of “friend”?

Body:
You could extract this to a separated service that has the only resposnsibility to track Container<->Item associoations. I think this is a very flexible solution.

class Container<T>
{
    private IItemAssociations associations;
    public Container(IItemAssociations a)
    {
        this.associations = a;
    }

    public void Add(T i)
    {
        if (!associations.IsAddedToAContainer(i))
        {
            DoAdd(i);
            associations.AddAssociation(this, i);
        }
        else
            HandleAlreadyAdded(i);
    }
}

You can have a static constructor method that injects a global association object or use some other injection mechanism.


问:
How can one guarantee unique identifiers, even in the case of system collapse and restoration from backup
In the manufacturing of a device each one has to get a unique identifier. So far so good, one can have a file containing the last used ID on a shared drive, or a network-based service managing and assigning IDs so that the uploading of the ID into the device will not be limited to a single workstation.

However, in the case of a total system crash and restoration from backup, one can have a few devices with the same ID, if some devices were manufactured after the backup was made.  One could have each workstation save the biggest used ID, and check whether it's not larger than the one they got from the network, but it might happen that the workstation with the last produced device is not turned on after the crash. One might require workers to write down the last used ID after their shifts, but this doesn't sound to be fool-proof either.

Is there a best practice besides having multiple services managing the IDs, with at least one of them off-site?

The IDs are large enough (32 bits) compared to the number of devices to be produced to allow for small gaps, but not large enough to go the true RNG way. This way, one can increase the largest ID by a number significantly larger than the amount being produced per day, but how can one keep this "company practice" enforced for possibly decades?

答:
Split your 32 bits.
Under normal operation, you count normally using all 32 bit.
When a crash actually happens, you use only the most significant, e.g., 8 bits of the backup, increment that part by two and start from there.
All you need to make sure now is that you backup often enough.
More specifically, often enough to ensure you didn't use up the whole lower significant part (24 bit in this example) in between backups.</p>


答:
There are a whole range of reasons that might be true, but the key ones are likely to be:

Hash tables are easier to implement than trees. Neither is entirely trivial, but hash tables are a bit easier, and the impact on the domain of legal keys is less stringent as you just need a hashing function and an equality function; trees require a total order function, and that's a lot harder to write.

Hash tables (may) have better performance at small sizes. This matters a lot because a significant fraction of work only theoretically deals with large datasets; in practice, much actually works with only tens or hundreds of keys, not millions. Small scale performance matters a lot, and you can't use asymptotic analysis to figure out what is best there; you have to actually implement and measure.

Easier to write/maintain, and a performance winner in typical use cases? Sign me up, please!

Body:
Why does Python use hash table to implement dict,  but not Red-Black Tree?

What is the key? Performance?


问:
Fighting technical debt as the "lowest developer"?
Let's say you work for a company and what you do is develop software for them. You have no idea of the big picture or maybe slight. What you do have are tasks assigned to you via issue tracking system. You're given tasks, you make them work the way the task describes them, you send them back. Like adding 2 integers:

```<code>function add(a,b){return a + b;}
</code>```

But later, as the project goes forward, you notice that as add becomes more complex, you realize that it should have needed some form of architecture, more than just a function that adds parameters and returns a value. However, you didn't know that. In the first place, all they needed was that simple add. You didn't expect add to become so complex.

The project progresses with more features, which you didn't expect to have in the first place. And in the end, you keep piling up hacks and layer upon layer of functions to avoid breaking/rewriting the existing code.

How do you deal with these situations? How do you fight technical debt as "the lowest developer"?

Clarification:

You're the "implementer", the lowest in the hierarchy.

You see the problem, but have no say with the matter.

I'm not quantifying technical debt or looking for tools.

Regarding the third "duplicate"

Refactoring & Rewrite - You are locked to your tasks. You are not paid to do extra.

Architecture Overview - You know the overall system, but no idea of the architecture.

Code Freeze - Not your call. You're not management.

Modularization - No idea of architecture. Modules change as requirements change.

Automated Tests - None exists.

答:
You do this the same way a clerk in a law office fights unethical behavior, a fast food worker fights unsanitary behavior, or a parking enforcement officer fights police corruption.

Be a good example.  To the extent you can, produce clean and sensible code.  When given a choice, choose the one that meets your requiremets with less downside.  (Be aware that technical debt is not unlike mortage debt -- just having it isn't necessarily a bad thing.)

Communicate your concerns.  You should have someone, either a team lead or customer or architect, who has the actual responsibility for managing technical debt and allocating your enterprise's resources.  When you see something that you believe is bad, communicate your concern to them.  Put it in writing (i.e., an email) if you're not confident that they will understand, respond to, and give credit for your input.

Don't stress.  Technical debt rarely causes the employment-ending failure of an enterprise.  So long as you've communicated your concerns and are doing your work, arcitecture issues such as technical debt are literally not your problem.  Yes, they may affect you, but they're no more your worry than a sheriff's re-election is the worry of a junior police officer.

In the example you provided, with an add function that has suffered complete feature creep, take a few minutes and draft the outline of what would improve it.  Send that to whomever you would need approval to implement it, and move on.

Assuming your enterprise was managed by extremely competent people and structured correctly, either your concern would be routed to the right system designer for a decision or you would be given leeway to implement your suggestion.  As a junior developer, I'd worry more about learning how your enterprise works than technical debt -- and if you know the former, how to handle the latter should be obvious.


问:
Dealing with co-workers who do not have a consistent coding style?
What do you when you're working with someone who tends to write stylistically bad code? The code I'm talking about is usually technically correct, reasonably structured, and may even be algorithmically elegant, but it just looks ugly. We've got:

Mixture of different naming conventions and titles (underscore_style and camelCase and UpperCamel and CAPS all applied more or less at random to different variables in the same function)

Bizarre and inconsistent spacing, e.g. Functioncall  (arg1 ,arg2,arg3 );

Lots of misspelled words in comments and variable names

We have a good code review system where I work, so we do get to look over and fix the worst stuff. However, it feels really petty to send a code review that consists of 50 lines of "Add a space here. Spell 'itarator' correctly. Change this capitalization. etc."

How would you encourage this person to be more careful and consistent with these kinds of details?

答:
One of my colleagues writes html in such a way that it makes my skin crawl.  Imagine my html nice and structured with two space indents, hacked to pieces by tags added to the end of mine which end on the same line or on the next like some drunk who needs to throw his arm around you to stay standing.  New lines are rarely indented but if they are, I'm sure there's some highly chaotic black hole in some part of the galaxy spitting out irrational temperature values in such a way that somehow its digits mirror the number of spaces or tabs used in such indentation by this woman.  If I'm lucky, I'll see an input tag that's closed with "</input>".  Total nightmare you can understand.

Nobody seems to understand this either, seeing how for most higher ups here, organized code or unorganized code to them is like the difference between us putting swiss cheese or american cheese on our sandwiches, which is to say, they could really care less.  I started letting it slide because I was stressed with another project, and I think she began to realize how difficult it was to understand code like that before she wanted to improve.  My advice would be to demonstrate why it's preferable to style your code more than simply telling them to do it.


答:
Every time you notice something like that, enter a new ticket into your issue tracking system.

Make a habit to use issue tracker as a primary tool to communicate stuff like that, because from there, it will be easy to pick, evaluate and prioritize for your senior colleagues / lead / manager / whoever is responsible for tracking the issues in your project.

Use the right tool for the job. I do it always and strongly recommend you do the same.

As an example, here is a ticket I created about a month ago. Upon completion of particular feature I discovered that code became substantially more complicated than it was before but I can't fix that within deadline given for feature implementation.

(Names of the features, tickets and code used in the real tracker is obscured, but the text is copied as is).

Summary: simplify design involving ParticularPieceOfCode

Description:

  In the course of implementation per TICKET-12345, code involving usage of ParticularPieceOfCode accrued a bit of complication and became rather difficult to read, understand and maintain (see example code snippet below).

Find a way to simplify it.

An example of code which would be desirable to redesign can be found in ClassName#methodName:

FWIW my advice applies independently of what "level" you are.

I've been using it at your current ("lowest") level and I am using it now that my level is quite far from "lowest" and I have satisfactory "say" as you call it, and I am going to use it always no matter what.

Just think of it, no level, no matter how much authority you have, there just can't be no better way.

If you "say" hey we've got an issue, it's only air rattling. And even if your boss / lead agrees and says you're right, we've got an issue, this changes nothing - it's only air rattling yet again, and it can't be anything else.

You may think that having your say written (eg in email) would be better, but if you think of it, it really isn't. If your project has substantial mail activity, what was written will be lost and long forgotten a month later.

Use the right tool for the job. For the job you describe, issue tracker is exactly the right tool.

You notice the issue, you enter it into system designed for tracking these and it takes care of the rest, in the best possible way - simply because it was designed for that:

computer software package that manages and maintains lists of issues, as needed by an organization... commonly used... to create, update, and resolve reported customer issues, or even issues reported by that organization's other employees... An issue tracking system is similar to a "bugtracker", and often, a software company will sell both, and some bugtrackers are capable of being used as an issue tracking system, and vice versa. Consistent use of an issue or bug tracking system is considered one of the "hallmarks of a good software team"href="http://www.joelonsoftware.com/articles/fog0000000029.html" rel="nofollow noreferrer" title="Joel Spolsky, 'Painless Bug Tracking'">1...

Whatever other means you would want to choose to communicate, having a ticket in tracker will only make it easier for you.

Even if you prefer to rattle the air, saying "I'd want to discuss TICKET-54321..." makes a more solid starting point than "Listen I'd want to talk about some piece of code I dealt with a while ago..." And you can safely pass the references to ticket by mail: even if mail gets lost, the issue will still be there in the tracker, with all the details you wanted to tell about.

Title: Fighting technical debt as the "lowest developer"?

Body:
Let's say you work for a company and what you do is develop software for them. You have no idea of the big picture or maybe slight. What you do have are tasks assigned to you via issue tracking system. You're given tasks, you make them work the way the task describes them, you send them back. Like adding 2 integers:

```<code>function add(a,b){return a + b;}
</code>```

But later, as the project goes forward, you notice that as add becomes more complex, you realize that it should have needed some form of architecture, more than just a function that adds parameters and returns a value. However, you didn't know that. In the first place, all they needed was that simple add. You didn't expect add to become so complex.

The project progresses with more features, which you didn't expect to have in the first place. And in the end, you keep piling up hacks and layer upon layer of functions to avoid breaking/rewriting the existing code.

How do you deal with these situations? How do you fight technical debt as "the lowest developer"?

Clarification:

You're the "implementer", the lowest in the hierarchy.

You see the problem, but have no say with the matter.

I'm not quantifying technical debt or looking for tools.

Regarding the third "duplicate"

Refactoring & Rewrite - You are locked to your tasks. You are not paid to do extra.

Architecture Overview - You know the overall system, but no idea of the architecture.

Code Freeze - Not your call. You're not management.

Modularization - No idea of architecture. Modules change as requirements change.

Automated Tests - None exists.

Body:
Every time you notice something like that, enter a new ticket into your issue tracking system.

Make a habit to use issue tracker as a primary tool to communicate stuff like that, because from there, it will be easy to pick, evaluate and prioritize for your senior colleagues / lead / manager / whoever is responsible for tracking the issues in your project.

Use the right tool for the job. I do it always and strongly recommend you do the same.

As an example, here is a ticket I created about a month ago. Upon completion of particular feature I discovered that code became substantially more complicated than it was before but I can't fix that within deadline given for feature implementation.

(Names of the features, tickets and code used in the real tracker is obscured, but the text is copied as is).

Summary: simplify design involving ParticularPieceOfCode

Description:

  In the course of implementation per TICKET-12345, code involving usage of ParticularPieceOfCode accrued a bit of complication and became rather difficult to read, understand and maintain (see example code snippet below).

Find a way to simplify it.

An example of code which would be desirable to redesign can be found in ClassName#methodName:

<a piece of code like one behind the right door here:>

FWIW my advice applies independently of what "level" you are.

I've been using it at your current ("lowest") level and I am using it now that my level is quite far from "lowest" and I have satisfactory "say" as you call it, and I am going to use it always no matter what.

Just think of it, no level, no matter how much authority you have, there just can't be no better way.

If you "say" hey we've got an issue, it's only air rattling. And even if your boss / lead agrees and says you're right, we've got an issue, this changes nothing - it's only air rattling yet again, and it can't be anything else.

You may think that having your say written (eg in email) would be better, but if you think of it, it really isn't. If your project has substantial mail activity, what was written will be lost and long forgotten a month later.

Use the right tool for the job. For the job you describe, issue tracker is exactly the right tool.

You notice the issue, you enter it into system designed for tracking these and it takes care of the rest, in the best possible way - simply because it was designed for that:

computer software package that manages and maintains lists of issues, as needed by an organization... commonly used... to create, update, and resolve reported customer issues, or even issues reported by that organization's other employees... An issue tracking system is similar to a "bugtracker", and often, a software company will sell both, and some bugtrackers are capable of being used as an issue tracking system, and vice versa. Consistent use of an issue or bug tracking system is considered one of the "hallmarks of a good software team"1...

Whatever other means you would want to choose to communicate, having a ticket in tracker will only make it easier for you.

Even if you prefer to rattle the air, saying "I'd want to discuss TICKET-54321..." makes a more solid starting point than "Listen I'd want to talk about some piece of code I dealt with a while ago..." And you can safely pass the references to ticket by mail: even if mail gets lost, the issue will still be there in the tracker, with all the details you wanted to tell about.


答:
I have never heard of an organization that didn't want it's employees to participate. You say that you are only paid to do the tasks. I sincerely doubt you have the right tasks in mind. Because you are paid to write good software.

Take this responsibility. Say no to adding features if you can't support the base. Advice the customer with your expertise. Step on the brakes now, before it's too late and you have to throw away the entire project, because it will no longer be maintainable.


问:
Deleting Content from Service
I'm not quite sure what the real practice is in the programming community. But when a user deletes content from your service (ie. deleting a status update, a photo of theirs, a comment they made). Should I actually delete them from my server or just hide it?

The reason why I am asking this is because we live in a age where the services we build are data hungry. The data is the most valuable aspect of the service you build and keeping everything that comes in is vital. What is the general practice for these type of situations?

What are your recommendations?

答:
You need to follow the Terms of Service (ToS) that you or the application owner have laid out.

If the ToS state that user content will be deleted, then you had better delete the content with the account.

If the ToS claim ownership over the data or anonymized abstraction of the data, then you are not obligated to delete the data.

It's also possible to state that you'll hold the data for N days just in case they decide to re-instate their account.  But again, you need to follow the ToS specifying what you'll do with the data after that N days elapses.

As mentioned in a comment, your service needs to be absolutely transparent in explaining:

what data is collected

what data is retained and for how long

what the data is used for

if the user has any ability to opt out of the data collection

what will be done with the data if / when the account is deleted

if / when accounts will automatically be deleted from lack of activity

You also asked:

The reason why I am asking this is because we live in a age where the services we build are data hungry. The data is the most valuable aspect of the service you build and keeping everything that comes in is vital.

And I'm going to point out that this line of reasoning is completely unrelated to the question of what you should do with the data.  The value of the data is completely irrelevant in whether or not you should honor requests to remove the data.  Saying that you won't delete the data despite the ToS just because you perceive it to be valuable is a false argument.

Case in point, certain very large social media sites have had their reputation hammered in the past for failing to respect ownership of that information.

Title: Deleting Content from Service


问:
Validating objects with each other - Design Pattern needed
I am running a zoo application.

My zoo includes an abstract class of 'animal', and several deriving classes - 'zebra', 'elephant', 'orangutan', 'baboon' and so on. Of each class I have several instances.

My question is: I want to check out if two animal instances can mate.

The business logic is divided to two parts:

I want to check if each mating partner is fit for mating, e.g. not too young or too old or sick etc.

I want to check if the two partners match - e.g. a zebra cannot mate an elephant, but an orangutan can mate with a baboon.

I assume the first requirement would be implemented by an abstract function which would reside under the animal baseclass. But what about the second requirement?

How would you design the classes in the most general matter that adding new types of animals would not require much of an overhead?

答:
According to Uncle Bob in Clean Code this is a typical example of when to write more procedural code and less object oriented. You want the flexibility to add "data structures", so you need to put the logic elsewhere.

Data/Object Anti-Symmetry

Procedural code (code using data structures) makes it easy to add new functions without changing the existing data structures.

OO code makes it easy to add new classes without changing existing functions.

Procedural code makes it hard to add new data structures because all the functions must change.

OO code makes it hard to add new functions because all the classes must change.

That's why Michael instinctively advised to have a function determine if 2 animals can mate.


问:
Why is CPU cache memory so fast?
What makes CPU cache memory so much faster than main memory? I can see some benefit in a tiered cache system. It makes sense that a smaller cache is faster to search. But there must be more to it.</p>

答:
Other answers already covered all the relevant bits: locality (and the associated data transfer cost, bus width and clock, and so on); speed of light (again, associated to transfer costs and bus width and throughput); different memory technology (SRAM vs.DRAM). All of this seen in the light of cost/performance balance.

One bit that was left out and it's just mentioned in  Darkhogg comment: larger caches have better hit rates but longer latency. Multiple levels of cache where introduced also to address this tradeoff.

There is an excellent question and answer on this point on electronics SE

From the answers, it seems to me that a point to be highlighted is: the logic which performs all the required operations for a cache read is not that simple (especially if the cache is set-associative, like most caches today). It requires gates, and logic. So, even if we rule out cost and die space

If someone would try to implement a ridiculously large L1 cache, the
  logic which performs all the required operations for a cache read
  would also become large. At some point, the propagation delay through
  all this logic would be too long and the operations which had taken
  just a single clock cycle beforehand would have to be split into
  several clock cycles. This will rise the latency.

Title: Why is CPU cache memory so fast?


问:
BSD/MIT license changes when copy/pasting a function from another BSD/MIT licensed package
I frequently find myself wanting to use some small function from another library but end up not doing because it's not worth pulling another dependency.

Considering BSD/MIT licenses, if I just copy/paste a function from another package, what would be the legal requirement when licensing my code? Also, as matter of netiquette, what would be the preferable way to give credit to the original author?

I understand this depends on the specific circumstances of each situation. The safe way would be to always ask the upstream author what does he want, but, sometimes, this happens so frequently that having a a default proposition for the upstream author can make the interaction smoother.

答:
You need to follow the terms of the license(s).1

1Honestly, that's it.

For the licenses you cite (BSD, MIT) there is nothing within the license terms that say you must use the entire module.  In fact, both of those licenses give you explicit permission to do what you're suggesting.

MIT

including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software

BSD

Redistribution and use in source and binary forms, with or without modification, are permitted ...

So go ahead and take those functions out of those modules that you want in order to avoid creating a dependency upon a whole library.

But what you can't do is fail to attribute the source of the code you used.  Both licenses require that you include a copy of the license as well as the copyright notice.

That may mean you need to put a prolog around the modules you copy and provide copyright attribution.  Or you may have to modify the license files to explicitly call out what portions of your code were sourced from where.  It's going to depend upon your project and the extent of how much you borrowed.

You also said:

The safe way would be to always ask the upstream author what does he want

But that's not quite true.  The upstream author has already expressly told you their intent through the license terms that they have released their code under.  You only need to contact the upstream author if you want to do something outside of the terms of the license.


答:
Are the changes you want to make your personal preferences or do you have an actual standard to follow? If you don't have an actual standard, then don't do this. First set a standard. Then you can get software that can be set to refactor the code to the standadrd settings (well at least of some things).

If you have a standard, start enforcing it in code review. There is no point to having a standard if you don't enforce it in code review. This will mean a lot of extra work in maintenance as people will have to fix old code that didn't meet the standard orginally when they touch it.

Even without a standard, insist on fixing mispellings in variable names (I wouldn't particularly worry about comments) as they will drive everyone who touches the code crazy forever.


问:
What is the benefit of offloading email to a transactional mail service?
Why do so many people recommend offloading email to a transactional service such as Mandrill, Postmark or Sendgrid?

Is sending email via smtp really that much slower than sending a request out to said service?

I imagine it has something to do with the rendering of the actual message, but I'd like a more informed reason.

答:
I don't think they are suggesting it for speed.

Sending emails becomes a problem when you need to send a lot of them from a single IP. That IP might end up as a spammer and so your emails will not be sent anymore.

Also if you try to send an email and it bounces for some reason, you the sender, must resend it, and check again if it fails and if so, send it again after some more time, and so on.

I think because of this two reasons, people recommend offloading email to some service.

The certainty the mail was sent and received is more important than the speed.


问:
Release an open-source project under multiple licenses
Consider this license I wrote for my software:

```<code>Copyright 2014, [my name]

The author(s) of this software intends to provide the users with the
maximum amount of freedom. As such, this software may be used under
any one of the following licenses:

1. MIT: [link to the license]
2. Apache 2.0: [link to the license]
3. BSD 2-clause: [link to the license]
4. BSD 3-clause: [link to the license]

Or, it can be considered released into the public domain in jurisdictions
where this is possible.

In any case, the software comes with absolutely no warranty.
</code>```

Do you guys see any potential problems with this licence, especially from a legal point of view?  Does it succeed in providing the users with the maximum amount of freedom?

答:
Not being lawyers, we can't give legal advise here.

What strikes me most in your license is the apparent contradiction that you start with Copyright 2014, [me] and also try to release the work into the public domain (which means that no copyright claims will be made).

Furthermore, providing multiple compatible permissive licenses to choose from does not really give me more rights than if you just choose one of them, but it does increase the amount of boilerplate legal text that needs to be included in each file.

It is far better to choose just one license with your software (which can be a public domain dedication). If you want to give as much freedom as possible, then I would recommend the MIT or 2-clause BSD license, or the Creative Commons CC0 if you want to release your software into the public domain.

Dual-licensing is mostly useful if you have common parts to two projects that use different licenses, or if you want to allow the use in closed-source applications only for paying customers (by using a dual license of GPL and closed-source)