问:
How to stop gold-plating and just be content to release working developments
The development team that I'm a member of has recently adapted to work according to Agile practices. This has personally highlighted the fact that I can't stop myself gold-plating code (and documentation) and I consequently exceed original estimates, when I could've delivered solutions that meet the requirements much earlier.

I think my ethic is bordering on the obsessive in that I become too attached to my code and am rarely content to release before I've refactored and perfected it to the nth degree. I am happy that I have realised this but how can I change my attitude/mentality to be content with my progress and release on-time instead?

答:
Gold Plated Software

The first time I saw gold plating used as a description for software was in a paper by Barry Boehm where he gave the following root cause:

Gold plating.  Fixed requirements specifications in advance of design
  tended to encourage software gold-plating.  Users asked about their
  requirements would frequently reason,  “ I don’t know if I’ll need
  this feature or not, but I might as well specify it just in case.”

In his description, he recommends using methods described in his research including the spiral software life-cycle model in which projects were scoped to produce a series of prototypes one per cycle, and as the spirals got bigger, a full featured product.  Spiral had wide spread influence among software researchers, and was an important bridge between waterfall and Agile.  A critical limitation of spiral is that each time around the spiral, cycles got longer and more expensive.

As with Agile, spiral tries to avoid gold plating by scoping more narrowly and scheduling the project deliverable long enough that teams can finish the requirements, while at the same time being short enough to permit focus on the goal from day one until delivery day.  One way that Agile methods like Scrum are superior is that Scrum sprints for a time frame that does not get longer with iterations.  From the paper, project management seems to have more influence on gold plating than than individual developers.

Talent for Time Boxing

Being able to time box is very important, but it is not a binary skill.   You don't have it or lack it.  You are better or less good with it.  Whether it comes from your boss or from you, I would prefer if no one said that you can't stop gold plating.  That sounds to personal, pervasive, and permanent.

A root cause analysis might help identify several issues.  I am quite certain they will not all be pointing at you, and that unless you work with psychopaths, others in your team will see similar needs to improve their Agile skill set.  If you know someone without problems, you don't know them very well.  If you know someone who thinks they don't need to improve, they don't know themselves very well.

I hope improvements you identify will be things you can solve with your own awareness and help from the team.  However, I think that is not where this ends.  My expectation from the supervisor or manager who writes your reviews would be that they can also coach their subordinates to be successful.  This is particularly critical when the organization is undergoing a revolutionary change like switching from planned to Agile (or ad-hoc to Agile).

Quick and Dirty or Risk Managed Prototype?

I had a manager who used to request that tasks be performed in certain way.

Quick and dirty, but a thing of beauty.

He knew the silliness of this, and it was part of his wry sense of humor.  Many people say things like this and they are dead serious.  Somewhere, there is a compromise or an opportunity to ease the problem with an improved technology or approach.

What can we sacrifice to fit our time box?

In chapter one of Extreme Programming Explained, second edition, Kent Beck talks about what it takes to move fast.  His answer is that "you do only what you need to do to create value for the customer."

Risk

In the first edition of the same book, Beck identifies a little more closely with Boehm's views about controlling risk as being critical to his methodology by saying:

"Risk is the basic problem of software development"

In both editions, Beck lists and describes eight common risks, followed by an assertion that XP (or perhaps by extension, Agile) addresses each in a particular way.  For me, most of his explanation boils down to use of smaller increments and faster iterations allows us to steer things back on course before the risks grow too big to handle.

Mentality of Sufficiency

Beck discusses resources in context of a story about the Mountain People and the Forest People and introduces a concept called the "Mentality of Sufficiency".  In the context of your situation he asks "How would you do it if you had enough time?"  Just this one first chapter, available as a book preview, may provide a lot of food for thought about how XP (and other Agile methods) think about constraints like time.

Compulsion Might be the Symptom, Not the Disease

Years ago I looked at a book about procrastination that stated that a lot of procrastination originates in fear.  If you don't start, you don't make a mistake, and maybe you won't be criticized.  Compulsion and perfectionism gives something that our moral sense tells us is better than procrastination, but probably has the same result.  Consider that perhaps you are having a problem with procrastination in another form?

Criticism and Competition

In Agile methodologies like Scrum, opportunities for being criticized or punished for procrastination have never been higher.  That is a vicious cycle.  I procrastinate because I am criticized, I am criticized because I procrastinate.  With daily scrum meetings, we are always on alert because we are always a day or less from reporting to the team what we accomplished.

In an ideal team, Scrum gives a daily opportunity to correct procrastination.  Mistakes should not have time to get big before help arrives.  Teams are not always where they should be trust-wise, so leaders within the team may need to proactively address either criticism or the fear of criticism to permit things to move forward.

In our world of work, each person on a team must also compete with others.  It is a little bit schizophrenic to believe in having a team that shares the work and the glory for accomplishments, but then use an annual performance management process that rewards 20% of its members, punishes or expels 10% or more of the members, and pretends that the 70% majority contributes its best without incentives.  I think this is a big elephant in the room WRT promoting teamwork, and to reference Kent Beck's story, it shows deep cultural ties to being Mountain People.

The Way Forward

As a member of an Agile team, it would be good to study and dialog with others about what works.  If your team is using TDD to automate their unit tests with a tool, get the person who does it best to coach you.  If your supervisor or manager has a problem with your documentation approach, find out what he likes or who is doing it the way he likes, and follow their approach.  If it boils down to raw coding speed, investigate what it takes to code faster.

Leaders can take steps in the right direction by role modeling desired behaviors like candid talk about their own problems (not someone else's), offering and following through with help, having a dialog about how the team can move to Agile Marine style (i.e. no man left behind).  Not everyone on the team has the same abilities.  It may be appropriate to explore pairing team members or assigning tasks and roles that can emphasizes complementary strengths of the people involved.  Planning for the growth or remediation of skills should be a rewarding part of the job both for the supervisor and the subordinate, but must happen early and often to be effective.


问:
In what practical ways is it good to remember the memory/pointers model?
A variable refers to a value. A variable is also stored in a memory address. People say that it's good to have this memory model in mind. Is that true? What is some sample code that shows this as beneficial in practice?

You dont have to use programming, you can use a real-world analogy if you like.

edit: they keep removing the helpful answer i summed up here -- no idea why

答:
I believe your question is not worded in a way that actually makes sense.  I think what you're really asking is, "Is it good to understand memory and pointers."

Say in C++ we have a class Dog.

```<code>Dog a = Dog();  // On stack
Dog *b = new Dog();  // On heap.
</code>```

'a' holds a value which is a Dog.

'b' holds a value that is a memory address that is on the heap (which we will find a dog hiding there).

'b' takes up space on the stack to hold the address so it'll only take up the size of a pointer on the stack.

'a' takes up space on the stack which is the size of a dog.

Say we want the dogs to bark now though...

```<code>a.bark();
b->bark();
</code>```

We have to treat our dogs differently.

```<code>b->bark();
(*b).bark(); // same as above
</code>```

We have to say, "Go to where b lives, and tell it to bark."  Most people don't get the difference and want to say.

```<code>b.bark();  // Won't work, might not even build.
</code>```

Because a pointer is just an location (which is just a number).  And a number cannot bark.  ('a' is a Dog.  'b' is the location of another dog.)

```<code>// We can even change what dog b points to.
b = &a;  // b will now hold the location to dog 'a'.
         // we will also have a dog that shall be lost forever D=!
b->bark();
a.bark();  // dog 'a' has now barked twice in a row since b points to a.
</code>```

Do you need to understand this?  Depends on what languages and tools you use.  In languages like Java and Python all of this is forced on you without you knowing it, it's handled by the language so you don't notice it.

Is it good to understand this?  Why yes...  yes it is.

Do you have to keep it active in your mind?  Well... lets allocate an array.

```<code>int stackArray[INT_MAX];  // Probably overflows the stack
int *heapArray = new int[INT_MAX];  // Allocates it all on the heap
                                    // or returns NULL if it cannot find the space.
</code>```

So yes.  At times.

(stackArray will actually be a pointer though... to memory on the stack)

ContentLicense: CC BY-SA 3.0

Body:
I believe your question is not worded in a way that actually makes sense.  I think what you're really asking is, "Is it good to understand memory and pointers."

Say in C++ we have a class Dog.

Dog a = Dog();  // On stack
Dog *b = new Dog();  // On heap.

'a' holds a value which is a Dog.

'b' holds a value that is a memory address that is on the heap (which we will find a dog hiding there).

'b' takes up space on the stack to hold the address so it'll only take up the size of a pointer on the stack.

'a' takes up space on the stack which is the size of a dog.

Say we want the dogs to bark now though...

a.bark();
b->bark();

We have to treat our dogs differently.

b->bark();
(*b).bark(); // same as above

We have to say, "Go to where b lives, and tell it to bark."  Most people don't get the difference and want to say.

b.bark();  // Won't work, might not even build.

Because a pointer is just an location (which is just a number).  And a number cannot bark.  ('a' is a Dog.  'b' is the location of another dog.)

// We can even change what dog b points to.
b = &a;  // b will now hold the location to dog 'a'.
         // we will also have a dog that shall be lost forever D=!
b->bark();
a.bark();  // dog 'a' has now barked twice in a row since b points to a.

Do you need to understand this?  Depends on what languages and tools you use.  In languages like Java and Python all of this is forced on you without you knowing it, it's handled by the language so you don't notice it.

Is it good to understand this?  Why yes...  yes it is.

Do you have to keep it active in your mind?  Well... lets allocate an array.

int stackArray[INT_MAX];  // Probably overflows the stack
int *heapArray = new int[INT_MAX];  // Allocates it all on the heap
                                    // or returns NULL if it cannot find the space.

So yes.  At times.

(stackArray will actually be a pointer though... to memory on the stack)


问:
Is time tracking required for web based/service industries?
I work in the web development industry and we implement a time tracking system to log our time (Project/time/comment). In the beginning of a project, we create a contract, and decide upon a price based on our hourly rate x estimated hours.

We log out times to see if we go "over budget". Is time tracking in this industry the norm? Is it required? What are the pros and cons?

答:
If what you are selling is your services you have to have a cost basis to use to set your prices. Human resources hours are by far the largest component of cost so yes you must have some way of knowing what those costs actually are.

You also need to know this to know how healthy your project is. If you've used 75% of the planned hours but only developed 50% of the product then you already know you are behind and don't have to wait till you blow the deadline before you start managing that problem. Yes you could do this with the calendar too but that isn't so precise and doesn't really help you recalibrate your estimates like you need to do.

ContentLicense: CC BY-SA 2.5


问:
Pulling changes from master to my work branch?
There's two of us working on something. We're using this branch structure

master

dev-A

dev-B

We both work on separate branches (dev-A,B) and whenever we're done - we promote our changes to master.

But the drawback of this is we can't get changes the other developer makes. Everything exists in the master tree - but we can't get the latest updates the other developer made.

Is there a way to resolve this or should we change our branch structure (per feature?)?

答:
I've seen developer branches used in two main scenarios:

The open-source community, where these branches are actually repository forks, so that project maintainers can lock down access to the master repository and require integration through pull requests. This makes life more difficult for contributors, but much easier for the maintainers, which of course is exactly the point, and this is a very successful model on GitHub.

Teams and organizations which do not have continuous integration and a track record of instability in their deployments, or worse, instability in their builds. These teams generally try to use developer branches as a way to protect the stability of the mainline, and the result is - typically - a long and very painful merge period before the release, followed by an even longer and more painful stabilization period, which sometimes doesn't happen until after the release.

I don't want this to be a rant about why you need CI, but it's clear from your question that you know you aren't integrating your changes often enough, so IMO there's no point in dancing around the issue.

Unless you're actually working in a geographically distributed team with a need to "gate" changes from outside developers, the branch-per-developer model really doesn't make much sense. It especially doesn't make sense with git, because every developer already technically has his/her own repository. Most organizations should be integrating very frequently - as in, several times per day.

I'm currently part of a group of about 35 contributors divided into 4 separate teams, most people check in at least 2-3 times a day, some people 10-15 times; it's unusual to see builds broken and extremely rare for them to stay broken for more than a few minutes. Git handles merges so effortlessly most of the time that remote developer branches are just unnecessary overhead. Just pull, merge locally, and run commit tests before you push, it's simple.

If you absolutely must defer integration in order to protect the stability of the master branch, the typical, proven model is to use an unstable branch - sometimes called a development branch, as described in A successful Git branching model. If developers can't successfully merge into this branch (which only needs to build, not run flawlessly) at least once a day, then you have a quality/discipline problem and not a revision control problem; covering it up by using non-integrated developer branches only defers the problem, and by doing so, actually makes the eventual merges a lot more painful and unstable than they really need to be.

Feature branches aren't the worst, but IMO very few projects are actually big enough to warrant them; if your project is very large (i.e. tons of features being worked on at once) then you'll see better results from splitting it up into separate autonomous components than you will from papering over the problem with source control.

You can ignore this advice if you want, and many teams do, but one of the reasons the branching model linked above is so popular and successful is that it's designed to work with continuous integration, not against it.


答:
I've also been annoyed with restrictions at work that take the fun out of programming, and to compensate I'll sometimes fire up a new project at home and "do it right".  The split allows me to satisfy both: my needs and the company's.

Or, you could develop a new skill other than programming to do in your off time that (eventually) satisfies what the job can't provide.

Title: How to stop gold-plating and just be content to release working developments

Body:
The development team that I'm a member of has recently adapted to work according to Agile practices. This has personally highlighted the fact that I can't stop myself gold-plating code (and documentation) and I consequently exceed original estimates, when I could've delivered solutions that meet the requirements much earlier.

I think my ethic is bordering on the obsessive in that I become too attached to my code and am rarely content to release before I've refactored and perfected it to the nth degree. I am happy that I have realised this but how can I change my attitude/mentality to be content with my progress and release on-time instead?

ContentLicense: CC BY-SA 4.0


问:
How important is it for a programmer to know how to implement a QuickSort/MergeSort algorithm from memory?
I was reviewing my notes and stumbled across the implementation of different sorting algorithms.

As I attempted to make sense of the implementation of QuickSort and MergeSort, it occurred to me that although I do programming for a living and consider myself decent at what I do, I have neither the photographic memory nor the sheer brainpower to implement those algorithms without relying on my notes. All I remembered is that some of those algorithms are stable and some are not. Some take O(nlog(n)) or O(n^2) time to complete. Some use more memory than others...

I'd feel like I don't deserve this kind of job if it weren't because my position doesn't require that I use any sorting algorithm other than those found in standard APIs. I mean, how many of you have a programming position where it actually is essential that you can remember or come up with this kind of stuff on your own?

答:
It's not really a matter of memorization. It's a matter of deeply understanding general classes of algorithms like divide and conquer. If you really understand divide and conquer, then you don't need to memorize quicksort. You can re-derive it on the spot as needed. Furthermore, the real payoff isn't even in being able to re-derive quicksort on your own, it's that you can recognize when a new problem is amenable to a divide and conquer solution.

Not all programming jobs are the same. Some jobs need a profound knowledge of algorithms, some need folks who understand type theory, and some just need folks that can scrape data from a web form and move it to a database. Some jobs even need all those skill at once. What kind of job do you want to work at?


问:
How can I get better at explaining complex software processes to developers?
I'm really struggling with my software specs.  I am not a professional programmer but enjoy doing it for fun and made some software that I want to sell later but I'm not happy with the code quality.  So I wanted to hire a real developer to rewrite my software in a more professional way so it will be maintainable by other developers in the future.

I read and found some sample specs and made my own by applying their structure to my document and wanted to get my developer friend to read it and give me advice.  After an hour and a half he understood exactly what I was trying to do and how I did it(my algorithms,stack,etc.).

How can I get better at explaining things to developers?  I add many details and explanations for everything(including working code) but I'm unsure the best way I can learn to pass detailed domain knowledge(my software applies big data, machine learning, graph theory to finance).  My end goal is to get them to understand as much as possible from the document and then ask anything they do not understand, but right now it seems they need to extract alot of information from me.  How can I get better at communicating domain knowledge to developers?

答:
Use metaphors.

From Herbjörn Wilhelmsen's blog:

A metaphor is an analogy between ideas. We use metaphors to explain or understand something in terms of something else...

...Human thinking depends on metaphor. We understand new or complex things in relation to things we already know...

...Metaphor stretches imagination in a way that can create powerful insights...

Prominent computer scientist Fernando J. Corbató said:

The value of metaphors should not be underestimated. Metaphors have the virtue of an expected behavior that is understood by all. Unnecessary communication and misunderstandings are reduced. Learning and education are quicker. In effect metaphors are a way of internalizing and abstracting concepts allowing one's thinking to be on a higher plane and low-level mistakes to be avoided.

From pp. 9-12 of Steve McConnell's Code Complete 2:

Important developments often arise out of analogies. By comparing a topic you understand poorly to something similar you understand better, you can come up with insights that result in a better understanding of the less-familiar topic. This use of metaphor is called "modeling"...

...In general, the power of models is that they're vivid and can be grasped as conceptual wholes. They suggest properties, relationships, and additional areas of inquiry...

...The history of science isn't a series of switches from the "wrong" metaphor to the "right" one. It's a series of changes from "worse" metaphors to "better" ones, from less inclusive to more inclusive, from suggestive in one area to suggestive in another...

...Software development is a younger field than most other sciences. It's not yet mature enough to have a set of standard metaphors. Consequently, it has a profusion of complementary and conflicting metaphors. Some are better than others. Some are worse....

...Over time, though, the person who uses metaphors to illuminate the software-development process will be perceived as someone who has a better understanding of programming and produces better code faster than people who don't use them.

In fact, McConnell speaks directly to your concern about using flawed or imperfect metaphors. [p. 20]

...Because metaphors are heuristic rather than algorithmic, they are not mutually exclusive... Use whatever metaphor or combination of metaphors stimulates your own thinking or communicates well with others or your team.

Using metaphors is a fuzzy business... If you extend them too far or in the wrong direction, they'll mislead you. Just as you can misuse any powerful tool, you can misuse metaphors, but their power makes them a valuable part of your intellectual toolbox.

And after you've mastered metaphors, learn how to draw.

Dan Roam's book entitled 'The Back of the Napkin' illustrates how the ability to draw can make anyone a very powerful communicator.

And you don't have to be Pablo Picasso. You just need to be neat and thoughtful.


问:
Language Design: Are languages like Python and CoffeeScript really more comprehensible?
The "Verbally Readable !== Quicker Comprehension" argument on http://ryanflorence.com/2011/case-against-coffeescript/ is really potent and interesting. I and I'm sure others would be very interested in evidence arguing against this. There's clear evidence for this and I believe it. People naturally think in images, not words, so we should be designing languages that aren't similar to human language like English, French, whatever.

Being "readable" is quicker comprehension. Most articles on Wikipedia are not readable as they are long, boring, dry, sluggish and very very wordy. Because Wikipedia documents a ton of info, it is not especially helpful when compared to sites with more practical, useful and relevant info. Languages like Python and CoffeScript are "verbally readable" in that they are closer to English syntax. Having programmed firstly and mainly in Python, I'm not so sure this is really a good thing.

The second interesting argument is that CoffeeScript is an intermediator, a step between two ends, which may increase the chance of bugs.

While CoffeeScript has other practical benefits, this question specifically requests evidence showing support for the counter-case of language "readability"

答:
I would answer "somewhat".

To be fair I think we have to first factor out our personal bias (ie. familiarity with keywords, syntax, and constructs) and only judge languages that we have never seen before.  (To judge the more popular languages we can only accept answers from new programmers as they are introduced to a the language for the first time.)  Then, given an identical implementation in several languages, the question posed should be "which of these is easier to understand"?

I would guess that the more there is a syntax hurdle the less likely a language will score well in this scenario, and that favors languages with a cleaner and more obvious syntax.

Much more likely to communicate the programmer's intent will be the choice of variable names and of course the comments that were included, and that transcends nearly all languages.


答:
I don't read code; I see patterns.

Eventually this applies to all the languages I learn.

The window where 'readable' matters is very short, a few days at most, even for idiomatic languages.

Title: Language Design: Are languages like Python and CoffeeScript really more comprehensible?

Body:
The "Verbally Readable !== Quicker Comprehension" argument on http://ryanflorence.com/2011/case-against-coffeescript/ is really potent and interesting. I and I'm sure others would be very interested in evidence arguing against this. There's clear evidence for this and I believe it. People naturally think in images, not words, so we should be designing languages that aren't similar to human language like English, French, whatever.

Being "readable" is quicker comprehension. Most articles on Wikipedia are not readable as they are long, boring, dry, sluggish and very very wordy. Because Wikipedia documents a ton of info, it is not especially helpful when compared to sites with more practical, useful and relevant info. Languages like Python and CoffeScript are "verbally readable" in that they are closer to English syntax. Having programmed firstly and mainly in Python, I'm not so sure this is really a good thing.

The second interesting argument is that CoffeeScript is an intermediator, a step between two ends, which may increase the chance of bugs.

While CoffeeScript has other practical benefits, this question specifically requests evidence showing support for the counter-case of language "readability"


问:
What's the opposite of cohesive?
I was talking with my architect about some concerns with a particular approach that may result in very low level of cohesion in a set of classes. However, I couldn't think of the word that represents a low level of cohesion.

I said something along the lines of "Obviously, we want cohesive classes not... uh ... not cohesive classes"

What's the correct word I should have used?

答:
Google repulsive and you get: repellent (among others).

Since each "class" appears to have an equal weighting relative to the others, a mutual or "peer energy" would be in order.  "repellent classes" seems to roll off the tongue fairly well.

Title: What's the opposite of cohesive?


问:
Whiteboard "testing" during an interview: legitimate way to back up your (whiteboard) code?
As I get it, having an error (even a typo like or missing ";") in your whiteboard code will often cost you some interview points. Avoiding that will inevitably make one proof-reading code again and again (losing time and possibly neural energy / concentration) or even using a simpler (and thus less effective) algorithm -- and both these ways are "costly" again!

So, why not just fast write code as elegant and effective as you would having a (unit) testing framework at your disposal and then just normally test it it (just on the whiteboard)?

Has anyone tried / seen this approach? Is the whole idea worthy?

[this also applies to the pen-and-paper case of course]

答:
When a restaurant wants to hire a chef, the owner doesn't ask him to cook a "pot au feu" with a toothpick and a cap.

Don't ask a developer to code on a whiteboard in an interview.


问:
What is the aim of software testing?
Having read many books, there is a basic contradiction:

Some say, "the goal of testing is to find bugs" while other say "the goal of the testing is to equalize the quality of the product", meaning that bugs are its by-products.

I would also agree that if testing would be aimed primarily on a bug hunt, who would do the actual verification and actually provide the information that the software is ready?

Even e.g. Kaner changed his original definition of testing goal from bug hunting to quality assessment provision but I still cannot see the clear difference. I perceive both as equally important.

I can verify software by its specification to make sure it works and in that case, bugs found are just by products. But also I perform tests just to break things.

Also what definition is more accurate?

Note above I am primarily referring to software testing as a process.

答:
I think investments in testing are taken to "improve the user experience".

Lots of times bugs are left in because they don't adversely affect the use of the product.  Likewise, "equalizing the quality of the product" will also be broken down by how useful it is to work on a particular area.  Lastly, the "good enough to ship" criteria must be recognized in that the end state for testing is always subjective.

Title: What is the aim of software testing?


答:
Let's ask Albert and see what he has to say on the subject:

“I don't need to know everything, I just need to know where to find it, when I need it”

-- Albert Einstein, paraphrased

Amen, Brother Albert, Amen.

Once you've made a good survey of the essential algorithms in any particular discipline (sort, search, whatever), you can then forget about the implementation details until you actually need the algo, in which case you go look it up or use a preexisting lib. 25 years ago I built a major search system using B*-trees, but today I would need to RTFM in order to use them well.

Title: How important is it for a programmer to know how to implement a QuickSort/MergeSort algorithm from memory?

Body:
I was reviewing my notes and stumbled across the implementation of different sorting algorithms.

As I attempted to make sense of the implementation of QuickSort and MergeSort, it occurred to me that although I do programming for a living and consider myself decent at what I do, I have neither the photographic memory nor the sheer brainpower to implement those algorithms without relying on my notes. All I remembered is that some of those algorithms are stable and some are not. Some take O(nlog(n)) or O(n^2) time to complete. Some use more memory than others...

I'd feel like I don't deserve this kind of job if it weren't because my position doesn't require that I use any sorting algorithm other than those found in standard APIs. I mean, how many of you have a programming position where it actually is essential that you can remember or come up with this kind of stuff on your own?


答:
Sorting and searching are amazingly important, whether you are a Donald Knuth fan or want to be the next Larry Page.  Depending on the business you are in, and the level of competition you can command among your candidates, I would recommend that you include some of the following concepts in the interview.

Sorting

Sketch of some kind of sorting algorithm.

List some examples of sorting algorithms.

Compare/contrast two sorts with different performance characteristics.

If they don't mention memory use, ask about it.

Searching

Name as many search algorithms as you can.

Compare/contrast two search algorithms.

Sketch any search other than linear search.

Some might say that requiring the code for these algorithms is overkill unless the job is on a deserted island with no internet connection.  Another consideration is that if you have 30 minutes, and you want to ask about anything else, for many candidates, implementing the sort could take a big chunk of your time.


答:
People naturally think in images

The author of that article shouldn't speak for everyone. Some people naturally think in images, others are more verbal/symbolic. Besides, his examples are of verbal versus symbolic. Neither && nor and is a picture; both are symbolic rather than pictorial, and both are processed by the same side of the brain. Symbolic reasoning is much closer to verbal reasoning than it is to spatial reasoning.

I for one am not a big fan of pictorial programming. It doesn't communicate to me. I never did like flow charts. I absolutely loathe UML diagrams as they inevitably bring out the worst in both worlds. Pictures make nice cartoons, great for presenting ideas to management. They're not so good for doing meaningful work in programming, mathematics, or physics (all of which are largely symbolic).

Sometimes pictures just don't cut it. Symbols are more powerful than pictures. Try drawing a picture of an infinite dimensional Hilbert space.


问:
Is extensive documentation a code smell?
Every library, open-source project, and SDK/API I've ever come across has come packaged with a (usually large) documentation file, and this seems contradictory to the wide-spread belief that good code needs little to no comments. What separates documentation from this programming methodology?

a one to two page overview of a package seems reasonable, but elegant code combined with standard intelisense should have theoretically deprecated the practice of documentation by now IMO.

I feel like companies only create detailed documentation and tutorials because its what they've always done.

Why should developers have to constantly be searching through online documentation in order to learn how to do things when such information should be intrinsic to the classes, methods and namespaces?

答:
I'm not sure what open source libraries you've been looking at, because most have crap for documentation.  That said...

First, before I decide I even want to use a library, I'd like to see some documentation explaining whether it will do exactly what I need it to do--I'd rather not have to download and search through source code to figure it out.

It's also a heck of a lot easier to search through a documentation file for desired functionality than it is to search source code.  I don't care how clearly you (think you've) named your classes, someone is going to not realize that the Fuu class really does Foo. An explanation written in English is going to help me to work this out.

API documentation in the form of javadoc (for example) can also be linked directly to the source code within IDEs (such as Eclipse), which also can make working with the library a lot easier.

So no, extensive documentation is a GOOD thing.  You don't have to read it if you don't want to, but I do.


问:
Should I add parameters to instance methods that use those instance fields as parameters?
I have an instance method that uses instance fields in its work. I can leave the method without that parameters as they're available to me, or I can add them to the parameter list, thus making my method more "generic" and not reliable on the class. On the other hand, additional parameters will be in parameters list. Which approach is preferable and why?

Edit: at the moment I don't know if my method will be public or private.

Edit2: clarification: both method and fields are instance level.

答:
Whether the input to the method should be in instance fields or in parameters depends on what the method does. It depends on the method’s semantics, the method’s relationship to the class and its semantics, and the fields’ purpose within the class. You didn’t specify any of these, so the answer could be anything.

In general, if it makes at all sense for the method do all its work from parameters instead of instance fields, then my first instinct would be to wonder why the method is even in that class. Perhaps it should be a static utility method in some static helper class.

Differently put, if you think there is no question that the method clearly should be an instance method in that class, then it should seem equally unequivocal for it to use the class’s instance fields — it should seem impossible to do it any other way. Since you’re pulling that into question, you should pull the premise into question.


答:
For libraries and public APIs, good documentation with sample code makes adoption much easier. The documentation does not have to be extensive (javadoc-style docs on every method are often useless), but should provide a to-the-point introduction on basic concepts and structure, as well as examples on a proper way to do common tasks with the API.

There are design decisions, patterns and recommended practices that a user cannot easily glean within a reasonable timeframe just by looking at the code, unless the API is extremely simple (which is not always possible).

Title: Is extensive documentation a code smell?

Body:
Every library, open-source project, and SDK/API I've ever come across has come packaged with a (usually large) documentation file, and this seems contradictory to the wide-spread belief that good code needs little to no comments. What separates documentation from this programming methodology?

a one to two page overview of a package seems reasonable, but elegant code combined with standard intelisense should have theoretically deprecated the practice of documentation by now IMO.

I feel like companies only create detailed documentation and tutorials because its what they've always done.

Why should developers have to constantly be searching through online documentation in order to learn how to do things when such information should be intrinsic to the classes, methods and namespaces?


问:
Is throwing an exception from a property bad form?
I've always been of the mindset that properties (ie, their set/get operations) should be fast/immediate and failure-free. You should never have to try/catch around getting or setting a property.

But I'm looking at some ways to apply role-based security on the properties of some objects. For instance an Employee.Salary property. Some of the solutions I've run across that others have tried (one in particular is the AOP example here) involve throwing an exception if the accessor doesn't have the right permissions - but this goes against a personal rule that I've had for a long time now.

So I ask: am I wrong? Have things changed? Has it been accepted that properties should be able to throw exceptions?

答:
Although a lot will depend on the context I'd generally avoid putting any sort of breakable logic (including exceptions) into properties. Just as one example, there's a lot of things which you (or some library that you're using) could do which use reflection to iterate over properties resulting in errors you didn't anticipate at design-time.

I say generally though as there may be some times when you absolutely, definitely, want to block something without worrying too much about the consequences. Security I guess would be the classic case there.


答:
Chiming in with the other two responses (+1 for both), good APIs are a nice to have, but good documentation is essential. Perhaps documentation isn't needed for a very simple package, one in which each object / each function stands on its own, and each object / each function does exactly what one would expect. A simple mathematical matrix/vector package, for example, might be self explanatory. Then again, maybe not. Even those simple packages oftentimes come with extensive documentation. Which matrix decomposition is best for this situation? For that one? Naive matrix operations inevitably thrashes memory. A good package will tell me how to use parts of the package in combination so as to avoid these problems. And that's a simple package.

In a toy package for a toy problem, objects and functions don't interaction, there are no dependencies, and interfaces are blindingly obvious just from the API. Life usually isn't that simple, and neither are most software packages.


答:
To have no documentation at all and to think that IntelliSense is all you need to understand the finest and subtlest details of what each class/method does, is illusory.

There are of course some very simple cases — for example, if a List class has a Count property, what could that property possibly return except the obvious. But a very significant amount of methods have corner-cases or behavioural properties that need to be documented for the benefit of the API user.

Let’s take an example:

```<code>public static TabPage ContainingTabPage(this Control control);
</code>```

Do you think it’s obvious what the method does? Well, its intention is certainly clear, but... what if the control is not contained in any TabPage? Does it return null or does it throw? What if it’s in multiple nested TabPages? — Fortunately, the documentation answers these questions: If this control is located within a TabPage, returns the first TabPage found by iterating recursively through its parents. Otherwise returns null. What would the method need to be called to make this documentation redundant? InnermostContainingTabPageOrNull()? That does not really contribute to code readability.

Or take something like this:

```<code>/// <summary>
/// Returns the smaller of the three IComparable values. If two values are
/// equal, returns the earlier one.
/// </summary>
public static T Min<T>(T val1, T val2, T val3) where T : IComparable<T>;
</code>```

In the majority of cases the second sentence in the documentation is irrelevant but does no harm. In the few cases where it does matter, it can save you a lot of time — if you don’t have the source code, you’d have to find the answer by experiment. In this case the experiment is easy, but imagine the method is about concurrency and you’re wondering about its thread safety or race conditions...

Another example: take an XML serializer. That’s simple, you might think, just have a XElement Serialize<T>(T) and a T Deserialize<T>(XElement) method and it’s totally clear what they do! Uhm, well, except... how does it serialize dictionaries? How does it handle interfaces? Does it preserve object identity? Does it cope with cyclic references without going into infinite loops? How does it behave when faced with the challenge of serializing delegates, native resources, remoting proxies? What exception types does it throw in which situations?

Only having two methods does not mean the process of serializing data is simple. Consequently, our custom XML serializer has a big thumping documentation block on the class which describes, in detail, all its features and all its limitations; what kinds of classes it can serialize, what assumptions it makes and what exceptions it throws; the custom attributes you can use to modify its behaviour; and, perhaps most importantly, what the fundamental design ideas behind it are and what use-cases it intends to cover (so that if your intended use-case is sufficiently different, you know you may be better off choosing a different serializer).

Now, with all that said, I think there is something to be said about quality vs. quantity. A lot of hobby-made libraries come with extra HTML files or other documents containing heaps of low-quality documentation when they could be more useful with less but better documentation. Good documentation needs to fulfill two important functions:

What does this class/method do? — This one is easy, just document each class/method.

How do I do X? — This one is hard. It may not be obvious to the API user what the method or class they need is called. To cover such cases, it often helps if the documentation for one method links to another (e.g. “if you are trying to do X, prefer to use M”) or the documentation for a class mentions all of the other classes with which it interacts (e.g. our above-mentioned XML serializer lists all the custom attributes that influence it). Some small code examples for common scenarios can be helpful, but only if they’re not trivially obvious.

There must be a small set of places to look for the answer. If the API user feels that they have to read pages after pages of irrelevant stuff only to ascertain that the answer they’re looking for isn’t in it, then the documentation is too badly structured and the API user may as well not bother reading it if it’s easier and faster to just ask on StackOverflow.

So, in summary: No, extensive documentation is not a code smell at all. Certainly you can’t improve the code simply by removing the documentation. But it may be a documentation smell. There is good documentation and there is bad documentation, and in some cases bad documentation may be improved by trimming it. Adding more documentation can make the documentation worse. Quality of documentation is not measured by number of words any more than code quality is measured by lines of code.

Body:
To have no documentation at all and to think that IntelliSense is all you need to understand the finest and subtlest details of what each class/method does, is illusory.

There are of course some very simple cases — for example, if a List class has a Count property, what could that property possibly return except the obvious. But a very significant amount of methods have corner-cases or behavioural properties that need to be documented for the benefit of the API user.

Let’s take an example:

public static TabPage ContainingTabPage(this Control control);

Do you think it’s obvious what the method does? Well, its intention is certainly clear, but... what if the control is not contained in any TabPage? Does it return null or does it throw? What if it’s in multiple nested TabPages? — Fortunately, the documentation answers these questions: If this control is located within a TabPage, returns the first TabPage found by iterating recursively through its parents. Otherwise returns null. What would the method need to be called to make this documentation redundant? InnermostContainingTabPageOrNull()? That does not really contribute to code readability.

Or take something like this:

/// <summary>
/// Returns the smaller of the three IComparable values. If two values are
/// equal, returns the earlier one.
/// </summary>
public static T Min<T>(T val1, T val2, T val3) where T : IComparable<T>;

In the majority of cases the second sentence in the documentation is irrelevant but does no harm. In the few cases where it does matter, it can save you a lot of time — if you don’t have the source code, you’d have to find the answer by experiment. In this case the experiment is easy, but imagine the method is about concurrency and you’re wondering about its thread safety or race conditions...

Another example: take an XML serializer. That’s simple, you might think, just have a XElement Serialize<T>(T) and a T Deserialize<T>(XElement) method and it’s totally clear what they do! Uhm, well, except... how does it serialize dictionaries? How does it handle interfaces? Does it preserve object identity? Does it cope with cyclic references without going into infinite loops? How does it behave when faced with the challenge of serializing delegates, native resources, remoting proxies? What exception types does it throw in which situations?

Only having two methods does not mean the process of serializing data is simple. Consequently, our custom XML serializer has a big thumping documentation block on the class which describes, in detail, all its features and all its limitations; what kinds of classes it can serialize, what assumptions it makes and what exceptions it throws; the custom attributes you can use to modify its behaviour; and, perhaps most importantly, what the fundamental design ideas behind it are and what use-cases it intends to cover (so that if your intended use-case is sufficiently different, you know you may be better off choosing a different serializer).

Now, with all that said, I think there is something to be said about quality vs. quantity. A lot of hobby-made libraries come with extra HTML files or other documents containing heaps of low-quality documentation when they could be more useful with less but better documentation. Good documentation needs to fulfill two important functions:

What does this class/method do? — This one is easy, just document each class/method.

How do I do X? — This one is hard. It may not be obvious to the API user what the method or class they need is called. To cover such cases, it often helps if the documentation for one method links to another (e.g. “if you are trying to do X, prefer to use M”) or the documentation for a class mentions all of the other classes with which it interacts (e.g. our above-mentioned XML serializer lists all the custom attributes that influence it). Some small code examples for common scenarios can be helpful, but only if they’re not trivially obvious.

There must be a small set of places to look for the answer. If the API user feels that they have to read pages after pages of irrelevant stuff only to ascertain that the answer they’re looking for isn’t in it, then the documentation is too badly structured and the API user may as well not bother reading it if it’s easier and faster to just ask on StackOverflow.

So, in summary: No, extensive documentation is not a code smell at all. Certainly you can’t improve the code simply by removing the documentation. But it may be a documentation smell. There is good documentation and there is bad documentation, and in some cases bad documentation may be improved by trimming it. Adding more documentation can make the documentation worse. Quality of documentation is not measured by number of words any more than code quality is measured by lines of code.


答:
Many modern programming environments are managed environments: they have automatic memory management, which means that you don’t have to worry about memory allocation and deallocation.

They replace the concept of memory and pointers with higher-level concepts such as local variables, fields, “references”, etc. You are now supposed to think of a local variable as some abstract storage location. You no longer have to worry about where in memory that location is and what you need to do with it in order for it to clean up correctly — that is abstracted away — but you do still need to worry about the high-level properties of the abstraction, like, say, the fact that assigning to a local variable obliterates its previous value.

Many experienced programmers who understand the whole system very well, have trouble separating this abstract higher level from the concrete lower level. For example they might directly think of a local variable as a memory location within the stackframe. Consequently, they perceive low-level details as more important than they are because they cannot imagine someone using local variables without understanding the stackframe. Personally I feel that such people make programming harder for newbies than it needs to be, both by complicating explanations of the higher-level concepts, and also by expecting newbies to find the low-level details important. Programming is all about abstraction and this is a very useful abstraction. (It doesn’t help that C’s/C++’s abstraction of local variables is really rather leaky, which makes some of the low-level details more important than they are in managed environments.)

This is not to say that we can all forget everything we know about pointers and stackframes and never teach it. Certainly if you’re interested in it then you should learn about it and broaden your understanding. You can occasionally benefit from the knowledge even when writing high-level code that doesn’t strictly require it (e.g. when optimizing it), and you certainly need it if you’re writing the memory management itself (e.g. a garbage collector). But you definitely shouldn’t feel that you can never be a “proper” programmer without understanding every last low-level detail. Even people who understand the stackframe may forget (or not know) that some local variables may be stored in a register instead. Even people who know about that may not know about the physical circuitry that makes up a register. We all use abstractions to make it easier to reason about our programs so we don’t have to go all the way down to electrons in silicon all the time.

Title: In what practical ways is it good to remember the memory/pointers model?

Body:
A variable refers to a value. A variable is also stored in a memory address. People say that it's good to have this memory model in mind. Is that true? What is some sample code that shows this as beneficial in practice?

You dont have to use programming, you can use a real-world analogy if you like.

edit: they keep removing the helpful answer i summed up here -- no idea why


问:
Processing a stream. Must layers be violated?
Theoretical situation:

One trillion foobars are stored in a text file (no fancy databases). Each foobar must have some business logic executed on it. A set of 1 trillion will not fit in memory so the data layer cannot return a big set to the business layer. Instead they are to be streamed in 1 foobar at a time, and have business logic execute on 1 foobar at a time.  The stream must be closed when finished.

In order for the stream to be closed the business layer must close the stream (a data operation detail), thus violating the separation of concerns.

Is it possible to incrementally process data without violating layers?

答:
The way I see it is this:

You have a data layer which provides functionality to read individual foobars, one at a time.

This functionality has an API. That API has a contract. Anyone wishing to use the API must adhere to the contract. The contract might specify, for example, that you must call NextFoobar() until you get null or something, and then you must stop calling it, but of course it could specify something more complex and it would simply be the contract to use.

The business layer doesn’t care how you implemented the API, it only needs to use this API to do what it needs to do. Using the API includes that it must adhere to the contract.

Now, if you look at the C#-based answer posted by @Job, it follows all of these principles:

The data layer provides an IEnumerable<Foobar> — an object that allows anyone to retrieve foobars from it, one at a time, without having to care where the foobars are coming from.

The API on IEnumerable<T> is well-defined. You can either use it the hard way (call GetEnumerator(), and then on the enumerator keep calling MoveNext() and Current until MoveNext() returns false, and then call Dispose()) or use a language feature or method that uses the API automatically (e.g. foreach or, in his case, .Count()).

The business layer correctly uses this API. It does need to call Dispose() (which it does indirectly by calling .Count()) but it doesn’t need to care what Dispose() actually does, it only calls it to fulfill the contract.

(Incidentally, if you enumerate all foobars, the file is not actually closed by the call to Dispose() but by the last call to MoveNext()... but Dispose() is still part of the API so that it can (and does) close the file if you decide to stop enumerating in the middle. The beauty of separation-of-concerns is that the business layer doesn’t need to care about any of that.)


问:
Why SQL is not so widespread in large desktop applications?
As a software developer, I've worked on projects ranging from tiny home-made apps to medium-size enterprise applications. In nearly every project I used a database or regretted choosing not to use it from the beginning.

Now, I am wondering a few things about the databases and their usage in general applications:

Why Windows itself doesn't use any "central" SQL database? For example:

Errors Reporting data is stored in a bunch of files,

Windows Update stores everything in flat files,

Icons cache is stored in a very strange single file which doesn't seem to be accessed through SQL, etc.

Why so many large applications avoid using databases? For example, wouldn't Microsoft Outlook gain by using a real database instead of reinventing the wheel by having its own format for .pst files and storing some data in registry?

If database adds an additional layer of an overall complexity and a tiny performance loss, it is a price of a huge advantage of making the code simpler in most circumstances, especially when it comes to the storage of small organized chunks of data instead of large binary streams. So why so few products are actually using databases? Probably the only application I know which actually uses Sqlite database is Firefox, and maybe Microsoft Exchange (but the last one is not a desktop application)?

Also, wouldn't a set of applications, like Microsoft Office or Microsoft Expression, benefit from having an unified SQL database, making it easier to deploy the applications, to update/upgrade the data, to share data between those applications, to make backups, etc.?

答: Relational databases are not the most efficient data structure for every domain. Lots of desktop applications do use embedded databases, you just can't readily tell they are doing it if all you see are a couple of data files.</p>


问:
Is there a way to get the version of Ubuntu that Google uses for development?
Is there a way to get the version of Ubuntu that Google uses for development?  Even better would be a full up VMWare or Virtual Box Virtual Machine image that might include a full complement of preinstalled tools as well.</p>

答:
Google insofar doesn't seem interested in releasing Goobuntu publicly:

A post on the Register, claiming that Google might be close to rolling out a "Goobuntu" Linux desktop distro, has been making the usual rounds in the tech news circuit today. Despite today being earnings release day, presumably a very busy time at the Google press relations office, technology spokeswoman Sonya Borälv responded very quickly to my query on the topic. She said that "[w]e use Ubuntu internally but have no plans to distribute it outside of the company."

Mark Shuttleworth, Canonical Ltd.'s founder, also notes:

I keep getting asked about Google’s “distribution of Ubuntu”, so perhaps this is a good place for me to say that as far as I’m aware there is absolutely no truth to the rumour that Google plans to distribute a derivative of Ubuntu as a Google OS. As exciting as that may be for Linux, it wouldn’t make sense for Google, and so far they’ve been pretty sensible about their projects.

Google uses lots of Linux internally, I imagine they also have their own versions of Red Hat, SUSE, Debian, perhaps even Gentoo and of course Ubuntu. So don’t read too much into their use of Ubuntu – it’s just part of the picture, and nothing to get overly excited about. The “goobuntu” you may have heard of is just a modified version of Ubuntu. Technically, there’s likely to be a “goobian” and a “goohat” too  . The good news is that the guys there have been good about sending us patches, and we do our best to integrate them into mainstream Ubuntu and push them on to Debian and upstream.

Thomas Bushnell, the tech lead of Google's Goobuntu team recently (August 29, 2012) discussed Goobuntu in his Ubuntu GNU/Linux at Google talk at LinuxCon, explaining that:

Bushnell explained that “Goobuntu is simply a light skin over standard Ubuntu.” In particular, Google uses the latest long term support (LTS) of Ubuntu. That means that if you download a copy of the latest version of Ubuntu, 12.04.1, you will, for most practical purposes, be running Goobuntu.

Google uses the LTS versions because the two-years between releases is much more workable than the every six-month cycle of ordinary Ubuntu releases. Besides, Google also tries to update and replace its hardware every two-years so that syncs nicely as well.

...without mentioning any plans to release Goobuntu publicly. Furthermore Bushnell mentions that Goobuntu uses proprietary software:

On top of this, Google has very strict security requirements. As Bushnell observes, “Google is a target Everyone wants to hack us.” So some programs that are part of the Ubuntu distribution are banned as potential security risks. These include any program “that calls home” to an outside server. On top of that Google uses its own proprietary in-house user PC network authentication that Bushnell says is “pushing the state of the art in network authentication, because we're such a high profile security target.”

That's possibly one of the reasons Google doesn't really seem interested in releasing Goobuntu publicly, at least anytime soon.


问:
"TDD is about design, not verification"; concretely, what does that mean?
I've been wondering about this. What do we exactly mean by design and verification.

Should I just apply TDD to make sure my code is SOLID and not check if it's external behaviour is correct?

Should I use BDD for verifying the behaviour is correct?

Where I get confused also is regarding TDD code Katas, to me they looked like more about verification than design; shouldn't they be called BDD Katas instead of TDD Katas?

I reckon that for example the Uncle Bob bowling Kata leads in the end to a simple and nice internal design but I felt that most of the process was centred more around verification than design. Design seemed to be a side effect of testing the external behaviour incrementally. I didn't feel so much that we were focusing most of our efforts on design but more on verification. While normally we are told the contrary, that in TDD, verification is a side effect, design is the main purpose.

So my question is what should I focus on  exactly, when I do TDD: SOLID, external API usability, or something else?

And how can I do that without being focused on verification?

What do you guys focus your energy on when you are practising TDD?

答:
```<code>> tdd is about design not verification.
</code>```

I would translate this to "the benefit of tdd is good design".

In tdd you concentrate on writing verification code.

By doing tdd (=writing tests in isolation before implementing the code) you get good design (=minimal coupling) automatically as a side effect.

Opposed to writing automated tests after implementing code you get verififcation as well but without the extra design benefit.

Body:
> tdd is about design not verification.

I would translate this to "the benefit of tdd is good design".

In tdd you concentrate on writing verification code.

By doing tdd (=writing tests in isolation before implementing the code) you get good design (=minimal coupling) automatically as a side effect.

Opposed to writing automated tests after implementing code you get verififcation as well but without the extra design benefit.


问:
Internal Mutation of Persistent Data Structures
To clarify, when I mean use the terms persistent and immutable on a data structure, I mean that:

The state of the data structure remains unchanged for its lifetime. It always holds the same data, and the same operations always produce the same results.

The data structure allows Add, Remove, and similar methods that return new objects of its kind, modified as instructed, that may or may not share some of the data of the original object.

However, while a data structure may seem to the user as persistent, it may do other things under the hood. To be sure, all data structures are, internally, at least somewhere, based on mutable storage.

If I were to base a persistent vector on an array, and copy it whenever Add is invoked, it would still be persistent, as long as I modify only locally created arrays.

However, sometimes, you can greatly increase performance by mutating a data structure under the hood. In more, say, insidious, dangerous, and destructive ways. Ways that might leave the abstraction untouched, not letting the user know anything has changed about the data structure, but being critical in the implementation level.

For example, let's say that we have a class called ArrayVector implemented using an array. Whenever you invoke Add, you get a ArrayVector build on top of a newly allocated array that has an additional item. A sequence of such updates will involve n array copies and allocations.

Here is an illustration:

However, let's say we implement a lazy mechanism that stores all sorts of updates -- such as Add, Set, and others in a queue. In this case, each update requires constant time (adding an item to a queue), and no array allocation is involved.

When a user tries to get an item in the array, all the queued modifications are applied under the hood, requiring a single array allocation and copy (since we know exactly what data the final array will hold, and how big it will be). Future get operations will be performed on an empty cache, so they will take a single operation. But in order to implement this, we need to 'switch' or mutate the internal array to the new one, and empty the cache -- a very dangerous action.

However, considering that in many circumstances (most updates are going to occur in sequence, after all), this can save a lot of time and memory, it might be worth it -- you will need to ensure exclusive access to the internal state, of course.

This isn't a question about the efficacy of such a data structure. It's a more general question. Is it ever acceptable to mutate the internal state of a supposedly persistent or immutable object in destructive and dangerous ways? Does performance justify it? Would you still be able to call it immutable?

Oh, and could you implement this sort of laziness without mutating the data structure in the specified fashion?

答:
A strong argument against allowing internal mutable state is that it requires synchronization. If multiple threads access the structure, you need to synchronize on operations that update the state.

I suggest you to read Okasaki's famous book Purely Functional Data Structures (PDF). It's worth it. In particular, he solves the question how to use laziness to make data structures that are persistent and immutable (I mean perfectly immutable, no internal changeable state except lazy evaluation and memoization of evaluated values - just what Haskell does).

Not only he describes structures with efficient amortized costs, he also describes structures that have efficient worst-case costs. The idea is to force a small part of unevaluated computations at each operation.

To give an example how it can work, in Section 4.2 he describes real-time queues. In Haskell, it'd look like

```<code>module RTQueue(RTQueue(), empty, add, headQ, tailQ) where

-- Invariant: |schedule| = |front| - |rear|
data RTQueue a = RTQueue { front :: [a], rear :: [a], schedule :: [a] }

empty = RTQueue [] [] []

-- Smart constructor that preserves the invariant.
-- We get |f| - |r| + 1 = |s| and fix it so that
-- the invariant |f| - |r| = |s| holds.
-- Either we force another element of `s` or
-- if `s` is empty we perform a rotation.
queue :: [a] -> [a] -> [a] -> RTQueue a
queue f r (_:s')  = RTQueue f r s'
queue f r []      = let f' = rotate f r []
                    in RTQueue f' [] f'
  where
    -- rotate f r a = f ++ reverse r ++ a
    -- and always |r| = |f| + 1
    rotate :: [a] -> [a] -> [a] -> [a]
    rotate []     [y]    a  = y : a
    rotate (x:f') (y:r') a  = x : rotate f' r' (y : a)

add :: RTQueue a -> a -> RTQueue a
add (RTQueue f r s) x = queue f (x : r) s

headQ :: RTQueue a -> a
headQ (RTQueue (x:_) _ _) = x

tailQ :: RTQueue a -> RTQueue a
tailQ (RTQueue (_:f) r s) = queue f r s
</code>```

The queue is split into two parts: front from which we take elements and rear which is reversed and to which we prepend elements. From time to time we rotate the queue - we reverse rear and append it to front. The third value schedule holds front after each rotation, but during each add (or tailQ) one of its element is forced (this is done simply by pattern matching on it in queue). The result is that the front list is gradually evaluated and is ready when needed by headQ or a subsequent rotate. This queue has worst-case complexity O(1) for its operations.

There is a functional data structure (not known at the time Okasaki wrote his book) that allows to represent finite sequences with amortized constant access time to both ends and amortized logarithmic access times anywhere, including logarithmic union time. See Data.Sequence.

Body:
A strong argument against allowing internal mutable state is that it requires synchronization. If multiple threads access the structure, you need to synchronize on operations that update the state.

I suggest you to read Okasaki's famous book Purely Functional Data Structures (PDF). It's worth it. In particular, he solves the question how to use laziness to make data structures that are persistent and immutable (I mean perfectly immutable, no internal changeable state except lazy evaluation and memoization of evaluated values - just what Haskell does).

Not only he describes structures with efficient amortized costs, he also describes structures that have efficient worst-case costs. The idea is to force a small part of unevaluated computations at each operation.

To give an example how it can work, in Section 4.2 he describes real-time queues. In Haskell, it'd look like

module RTQueue(RTQueue(), empty, add, headQ, tailQ) where

-- Invariant: |schedule| = |front| - |rear|
data RTQueue a = RTQueue { front :: [a], rear :: [a], schedule :: [a] }

empty = RTQueue [] [] []

-- Smart constructor that preserves the invariant.
-- We get |f| - |r| + 1 = |s| and fix it so that
-- the invariant |f| - |r| = |s| holds.
-- Either we force another element of `s` or
-- if `s` is empty we perform a rotation.
queue :: [a] -> [a] -> [a] -> RTQueue a
queue f r (_:s')  = RTQueue f r s'
queue f r []      = let f' = rotate f r []
                    in RTQueue f' [] f'
  where
    -- rotate f r a = f ++ reverse r ++ a
    -- and always |r| = |f| + 1
    rotate :: [a] -> [a] -> [a] -> [a]
    rotate []     [y]    a  = y : a
    rotate (x:f') (y:r') a  = x : rotate f' r' (y : a)

add :: RTQueue a -> a -> RTQueue a
add (RTQueue f r s) x = queue f (x : r) s

headQ :: RTQueue a -> a
headQ (RTQueue (x:_) _ _) = x

tailQ :: RTQueue a -> RTQueue a
tailQ (RTQueue (_:f) r s) = queue f r s

The queue is split into two parts: front from which we take elements and rear which is reversed and to which we prepend elements. From time to time we rotate the queue - we reverse rear and append it to front. The third value schedule holds front after each rotation, but during each add (or tailQ) one of its element is forced (this is done simply by pattern matching on it in queue). The result is that the front list is gradually evaluated and is ready when needed by headQ or a subsequent rotate. This queue has worst-case complexity O(1) for its operations.

There is a functional data structure (not known at the time Okasaki wrote his book) that allows to represent finite sequences with amortized constant access time to both ends and amortized logarithmic access times anywhere, including logarithmic union time. See Data.Sequence.


问:
Design patterns frequently seen in embedded systems programming
I don't have any question related to coding. My concerns are about embedded systems programming independent of any particular programming language.

Because I am new in the realm of embedded programming, I would quite appreciate responses from those who consider themselves experienced embedded systems programmers.

I basically have 2 questions.

Of the design patterns listed below are there any seen frequently in embedded systems programming?

Abstraction-Occurrence pattern

General Hierarchy pattern

Player-Role pattern

Singleton pattern

Observer pattern

Delegation pattern

Adapter pattern

Facade pattern

Immutable pattern

Read-Only Interface pattern

Proxy pattern

As an experienced embedded developer, what design patterns have you, as an individual, come across? There is no need to describe the details. Only the pattern names would suffice. Please share your own experience.

I believe the answers to the above questions would work as a good starting point for any novice programmers in the embedded world.

答:
Embedded Systems Growing, Expect Broad Pattern Support

As embedded systems start to have more memory and processor available, and shift from bare metal, to real-time-kernels, to embedded versions of Linux and Windows or even to Android, I suspect they will pick up all these patterns and more.

Pattern Limiting Factors

Not sure how to make a table, but your list could be evaluated for suitability to be implemented on bare metal, with an RTK, or with an OS.  There may be variations dependent on computer languages, with assembler or embedded C++ potentially being restrictive, C lacking object orientation to facilitate some of the patterns, and C++ (or its features) being either unavailable or prohibited by coding standards like MISRA.

Coding Standard and Real-Time Interaction with Patterns

Some embedded systems projects forbid use of dynamic memory.  This puts a real damper on some of the patterns.  Others may either hurt or help with the amount of memory required.  Use of managed code techniques can introduce unwanted latency during garbage collection.

Patterns as a Starting Point?

I believe the answers to the above questions would work as a good
  starting point for any novice programmers in the embedded world.

I think this statement is a bit of a jump.  Patterns are something of a meta-concept and are no substitute for down and dirty details like memory maps, programming peripheral devices like timers, uarts, SPI, I2C, ATOD/DTOA, PWM, etc. or creating interrupt services routines.  If you are using an OS, you will need some kind of board support package.  If you are using COTS, you need to evaluate which products.

If you are doing custom hardware, there is interaction with electrical engineers and some training to cope with reading schematics and reading (or maybe writing) data sheets and theory of operations documents.  Using test equipment like Oscilloscopes, logic analyzers, JTAG or In-Circuit Emulators and IDE based cross development tools from Windows, Linux or even Mac.

Embedded Systems On Stack Exchange?

There was an Embedded Systems site for Stack Exchange that was in the Commitment stage in Area 51.  It was closed due to a two year time limit.  There are several embedded related proposals including a beta for Raspberry Pi, a BeagleBoard with two followers, and an Arduino proposal that is also closed.

http://area51.stackexchange.com/proposals/15961/embedded-system-design-and-development

There is a procedure for reopening or reproposing a site.  If anyone is up for it, let's give it a try.


问:
.Net C# Remote Method Invocation (RMI) (Client/Server communication)
What exactly is C# version of Java RMI?

I want to invoke the methods of client from the server, ping the client from server etc.

How the server and client communication is done with c#?

答:
As svick said in his comment Windows Communication Foundation would be the technology in question.

Introduced in .NET 3.0, its goal was to pull together all manner of client-server communications, replacing various disparate methods (webservices, remoting, message queueing, etc.) with a single unified framework.


问:
Do compilers have to be written for each model of CPU?
Do you need to take account of the different processors and their instructions when writing a compiler? Have instructions been standardised? Or what tools and techniques are available to assist with this? E.g. Ignoring machine instructions that are specific to a certain processor model.</p>

答:
No, instruction sets aren't "standardized" in a way that you could produce assembly that's fit for – or is simply mappable to – ARM, x86, PPC, MIPS, Itanium, Sparc, ... (and their variants).

Native code compilers are pretty complex beasts. Not all the work they do is processor-specific. All the lexing/parsing is language-dependent but not chip-related. Some optimization passes are also hardware-independent, but possibly not all – e.g. the right code size v.s. raw speed tradeoffs might depend on the target.

At some point, if you're producing native code, you'll need to know the details of the chip you're targeting. You need to be aware of their "quirks" (memory coherency properties for instance) and complete instruction sets to produce an instruction stream that is both correct and reasonably efficient.

Even if you restrict yourself to one instruction set (say x86_64), different brands of chips have different extensions that need to be considered. Different models of the same brand also have instruction set differences (new features added, sometimes old features removed). Sticking with the "lowest common denominator" could work, but you'll be missing out on a lot of stuff.

Does that mean the you do a complete rewrite of the compiler for every new instruction set or extension that hits the market? Of course not. Those are incremental changes, sometimes only to "machine description files" or whatever the compiler uses to model the target instruction set.

But introducing a new ISA altogether is not a trivial task and requires detailed knowledge of the target.

If you're setting out to build a compiler yourself, do have a look at LLVM. Chances are you use it for the "emitting native code" part at least, whatever language it is you're trying to compile.

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.


答:
Paper or whiteboard tests are extremely ineffective. I remember once I had an interview where I had to look for errors in some code on paper. One of them was that the class inherited from an interface but was missing the implementation of a member. I knew this was likely to be one of the errors, I was looking for it and for whatever reason on the spot I just couldn't see it (although I did mention that I was looking for that as one of the issues).

As it happens, I still got that job, but it did make me think about what had happened. In a realistic scenario for that sort of thing I'm going to get squiggly lines the moment something's wrong (this is C# in Visual Studio) and the thing isn't going to compile. I never check for this in real life because it never happens (it is impossible) and hence I'm de-tuned from seeing this sort of thing. Missing semi-colons are an even more extreme example of this - totally unrealistic in the real world unless you're writing in notepad and e-mailing your code to someone else to compile!

If someone asks to use a whiteboard during an interview to support something they want to say then great, but I'd never do it the other way around.

Title: Whiteboard "testing" during an interview: legitimate way to back up your (whiteboard) code?

Body:
As I get it, having an error (even a typo like or missing ";") in your whiteboard code will often cost you some interview points. Avoiding that will inevitably make one proof-reading code again and again (losing time and possibly neural energy / concentration) or even using a simpler (and thus less effective) algorithm -- and both these ways are "costly" again!

So, why not just fast write code as elegant and effective as you would having a (unit) testing framework at your disposal and then just normally test it it (just on the whiteboard)?

Has anyone tried / seen this approach? Is the whole idea worthy?

[this also applies to the pen-and-paper case of course]


问:
is there any elegant way to analyze an engineer's process?
Plenty of sentiment exists that measuring commits is inappropriate.

Has any study been done that tries to draw in more sources than commits - such as:

browsing patterns

IDE work (pre-commit)

idle time

multitasking

I can't think of an easy way to do these measures, but I wonder if any study has been done.

On a personal note, I do believe that reflection on one's own 'metrics' could be valuable regardless of (or in the absence of) using these for performance eval.  I.E. an un-biased way to reflect on your habits.  But this is a discussion matter beyond Q&A.

答:
Not sure if you would consider it elegant, but Watts Humphrey wrote an entire book called Personal Software Process that was all about measuring your own productivity.  He outlined metrics for inputs like time at your desk vs. interruptions, time spent working on various kinds of software life cycle activities, defects per amount of code.  There is a technical report that gives the short version at:

http://www.sei.cmu.edu/library/abstracts/reports/00tr022.cfm

If you want to look at something like the quality of a developers code, Chidamber & Kemerer proposed several metrics for object oriented code.

Metrics for object oriented code

depth of inheritance tree,

weighted number of methods,

number of member functions,

number of children, and

coupling between objects.

Using a base of code, they tried to correlated these metrics to the defect density and maintenance effort using covariant analysis.  Later studies did similar analysis on hundreds of Source Forge Java projects to determine their characteristics relative to CK Metrics and some additional metrics proposed later.

Metrics arising in context of Code Reviews

Defects can be categorized by many criteria:

severity: (major, minor, cosmetic, investigate/unknown),

type (logic, typo, spelling, coding standard violation, etc.),

origin/phase containment (requirements, design, code, etc.).

There are also preparation and inspection rates (time per reviewer, time per line of code) and defect densities (per KLOC (thousand lines of code), per minute of inspector/reviewer time).

Plotting these values against control charts can show us whether we are within bounds for the process (for example, a team that inspects 200 lines of code that finds no defects in a group that averages twenty-five defects per KLOC might be malfunctioning).

Other metrics

Other metrics that could help include those for

earned value to help calibrate estimation

velocity for those using Scrum or Kanban.

The work of Pareto, Juran, Demming, Ishikawa, and others from quality and industrial engineering is somewhat portable to software development with a little bit of imagination.

Limitations of Analysis

There are tremendous limits on the value of metrics.  Bugs fixed per developer can mean almost anything, and when you start to punish or reward on that measurement, I bet bugs will get more numerous and granular, and the mix of difficult to easy bugs fixed will also change as the team cherry picks in the to race to have the most.

There is also a certain distraction and potentially a loss of focus and enjoyment that can come with intrusive measurement.  You can't get much more elegant (and emotionally burdened) than a lake poet like Wordsworth who said,

```<code>      Sweet is the lore which Nature brings;
      Our meddling intellect
      Mis-shapes the beauteous forms of things:--
      We murder to dissect.
</code>```

While software isn't exactly Nature, give me some latitude because I thought I would never get to use anything from high school English Literature class.

Agile might be considered a reaction to centralized, big process.  Sometimes that mode of work could require so much analytical effort that the ability to reach flow while creating software all but disappeared.

Body:
Not sure if you would consider it elegant, but Watts Humphrey wrote an entire book called Personal Software Process that was all about measuring your own productivity.  He outlined metrics for inputs like time at your desk vs. interruptions, time spent working on various kinds of software life cycle activities, defects per amount of code.  There is a technical report that gives the short version at:

http://www.sei.cmu.edu/library/abstracts/reports/00tr022.cfm

If you want to look at something like the quality of a developers code, Chidamber & Kemerer proposed several metrics for object oriented code.

Metrics for object oriented code

depth of inheritance tree,

weighted number of methods,

number of member functions,

number of children, and

coupling between objects.

Using a base of code, they tried to correlated these metrics to the defect density and maintenance effort using covariant analysis.  Later studies did similar analysis on hundreds of Source Forge Java projects to determine their characteristics relative to CK Metrics and some additional metrics proposed later.

Metrics arising in context of Code Reviews

Defects can be categorized by many criteria:

severity: (major, minor, cosmetic, investigate/unknown),

type (logic, typo, spelling, coding standard violation, etc.),

origin/phase containment (requirements, design, code, etc.).

There are also preparation and inspection rates (time per reviewer, time per line of code) and defect densities (per KLOC (thousand lines of code), per minute of inspector/reviewer time).

Plotting these values against control charts can show us whether we are within bounds for the process (for example, a team that inspects 200 lines of code that finds no defects in a group that averages twenty-five defects per KLOC might be malfunctioning).

Other metrics

Other metrics that could help include those for

earned value to help calibrate estimation

velocity for those using Scrum or Kanban.

The work of Pareto, Juran, Demming, Ishikawa, and others from quality and industrial engineering is somewhat portable to software development with a little bit of imagination.

Limitations of Analysis

There are tremendous limits on the value of metrics.  Bugs fixed per developer can mean almost anything, and when you start to punish or reward on that measurement, I bet bugs will get more numerous and granular, and the mix of difficult to easy bugs fixed will also change as the team cherry picks in the to race to have the most.

There is also a certain distraction and potentially a loss of focus and enjoyment that can come with intrusive measurement.  You can't get much more elegant (and emotionally burdened) than a lake poet like Wordsworth who said,

      Sweet is the lore which Nature brings;
      Our meddling intellect
      Mis-shapes the beauteous forms of things:--
      We murder to dissect.

While software isn't exactly Nature, give me some latitude because I thought I would never get to use anything from high school English Literature class.

Agile might be considered a reaction to centralized, big process.  Sometimes that mode of work could require so much analytical effort that the ability to reach flow while creating software all but disappeared.


问:
What actually is a module in software engineering?
According to Stephen Schach, “Classical and Object-Oriented Software Engineering”, chapter 6:

a module consists a single block of code that can be invoked in the way that a procedure, function, or method is invoked

This seems very vague and broad. So could anyone explain it clearly and show some actual examples of how to break a requirement into modules? Thanks.

答:
There isn't a formal definition of a module, and what a module is (or isn't) in the context of your project largely depends on the nature and design of the project.

Generally speaking a module is a standalone piece of code that provides specific and tightly coupled functionality, modules define and enforce logical boundaries in your code.


答:
A module,

encapsulates code and data to implement a particular functionality.

has an interface that lets clients to access its functionality in an uniform manner.

is easily pluggable with another module that expects its interface.

is usually packaged in a single unit so that it can be easily deployed.

For example, dapper.net encapsulates database access. It has an API to access its functionality. It is a single file that can plugged in a source tree to be built.

The concept of module comes from modular programming paradigm which advocates that software should be composed of separate, interchangeable components called modules by breaking down program functions into modules, each of which accomplishes one function and contains everything necessary to accomplish this.

Title: What actually is a module in software engineering?

Body:
According to Stephen Schach, “Classical and Object-Oriented Software Engineering”, chapter 6:

a module consists a single block of code that can be invoked in the way that a procedure, function, or method is invoked

This seems very vague and broad. So could anyone explain it clearly and show some actual examples of how to break a requirement into modules? Thanks.


答:
Module might be an overloaded term, so much that Wikipedia describes it under the term Modular Programming when discussing its use relative to software.  They discuss it in terms of structured programming which was based on a top-down design approach.  Key characteristics of modularity related to the use of low coupling and high cohesion.

My usage has been that in a language like C or even C++, a module is related to defining a separately compiled unit from a source file (.c or .cpp) and typically one associated header file (.h).  Other languages use module as a description, and the language Modula-2 put structuring around modules front and center in its name and its approach.

Historically, module has some other implications as were described in the D.L. Parnas paper "On the Criteria to be Used in Decomposing Software into Modules".  He is primarily concerned with discussing benefits of replacing functional decomposition with data oriented decomposition which was a big step toward our present state of the art which is object oriented decomposition.

Object oriented languages are organized around classes, so maybe the term module is less important and less precise in that context.


问:
Tips about how to spread Object Oriented practices
I work for a medium company that has around 250 developers. Unfortunately, lots of them are stuck in a procedural way of thinking and some teams constantly deliver big Transactional Script applications, when in fact the application contains rich logic. They also fail to manage the design dependencies, and end up with services which depend on another large number of services (a clean example of Big Ball of Mud).

My question is: Can you suggest how to spread this type of knowledge?

I know that the surface of the problem is that these applications have a poor architecture and design. Another issue is that there are some developers who are against writing any kind of test.

A few things I'm doing to change this (but I'm either failing or the change is too small are)

Running presentations about design principles (SOLID, clean code, etc).

Workshops about TDD and BDD.

Coaching teams (this includes using sonar, findbugs, jdepend and other tools).

IDE & Refactoring talks.

A few things I'm thinking to do in the future (but I'm concern that they might not be good)

Form a team of OO evangelists, who disseminate an OO way of thinking in differet teams (these people would need to change teams every few months).

Running design review sessions, to criticise the design and suggest improvements (even if the improvements are not done because of time constraints, I think this might be useful)

.

Something I found with the teams I coach, is that as soon as I leave them, they revert back to the old practices. I know I don't spend a lot of time with them, usually just one month. So whatever I'm doing, it doesn't stick.

I'm sorry this question is spattered with frustration, but the alterative to write this was to hit my head on the wall until I pass out.

答:
My experience is that switching from procedural mindset to OO mindset is a big hurdle. It requires perseverance which many developers fail to endure. This is mainly because the fundamentals of OO are looked over.

Form a team of OO evangelists, who disseminate an OO way of thinking in differet teams (these people would need to change teams every few months).

is a good idea. This should be thorough and OO should be talked about from ground up. When I was learning OO historical anecdotes helped a lot.

I would also suggest,

Since motivation is the key, motivate them detailing how OO can improve their work, especially code maintainability.

Do code review and show how to refactor applying composition, inheritance, polymorphism, and patterns.

Introduce a good process like SCRUM and engage developers in it.

Make reading books like 'Refactoring' and 'Refactoring to Patterns' mandatory.


问:
The 10 minutes technical interview
I must do a quick assessment of dozens of fresh students very quickly. I have 30 minutes meeting with each of them (in two or three days). I want to use most of the time to discuss non technical aspects. So I plan to use 10 minutes for technical questions. The same questions for all of them.

They are all hired already (they are students), what I need to know is the average level in order to prepare a training.

Ideally, the difficulty must be progressive in order to set a level for each. Level I will average, and I'll do an average on each question too.

If you had only 10 minutes and 10 questions to ask to a candidate, what would be your top 10 ?

答:
Explain pointers!

What are closures?

Which languages do you use in your spare time and why?

Talk a little about transactions!

What's the difference between an interpreter and a JIT?

Explain the basics of a compiler.

What happens on memory level when you do recursion (and what's different when you have TCO)

What are the important concepts of OO Programming (and why are they important)?

What new stuff are you looking into at home and why is it interesting?

Explain the difference between a process and a thread.

Title: The 10 minutes technical interview


问:
What is a good way to learn about multicore programming at the kernel level in Linux?
I am interested in multicore programming at the kernel level.  I expect this affects many areas and is probably different for each architecture.  What are some must read sections of the kernel?  If I wanted to compare and contrast code for an Intel I7 and an ARM Cortex-A9 MPCore where would I find the differences?</p>

答: There is nothing special about Multicore Programming in Linux. You have to understand the whole kernel. Instead of asking specific questions, go ahead and download the Linux Source code from kernel.org and go through the README file and the source code structure. (Your question about intel and arm process is answered in README). Start reading the source code along with a good linux kernel book. </p>


答:
It is really about both, but the verification is a nice side effect which could be accomplished by writing the tests after the code.  The real benefit of TDD and writing the test first is that it helps you flesh out the design by refining the design of each logical unit or business rule and building on the rest of the logical units without breaking the other units of the design and keeping them from becoming overly coupled.

For example some developers use the TDD approach almost like a "white board" where the tests and code all live in the same file initially. It gives a lot of freedom to evolve the logic with the tests, as well as test out ideas. Then as the design evolves the code is extracted out of the test module into the application itself.

The resulting tests can be used for verification as further refactoring is done.

Title: "TDD is about design, not verification"; concretely, what does that mean?

Body:
I've been wondering about this. What do we exactly mean by design and verification.

Should I just apply TDD to make sure my code is SOLID and not check if it's external behaviour is correct?

Should I use BDD for verifying the behaviour is correct?

Where I get confused also is regarding TDD code Katas, to me they looked like more about verification than design; shouldn't they be called BDD Katas instead of TDD Katas?

I reckon that for example the Uncle Bob bowling Kata leads in the end to a simple and nice internal design but I felt that most of the process was centred more around verification than design. Design seemed to be a side effect of testing the external behaviour incrementally. I didn't feel so much that we were focusing most of our efforts on design but more on verification. While normally we are told the contrary, that in TDD, verification is a side effect, design is the main purpose.

So my question is what should I focus on  exactly, when I do TDD: SOLID, external API usability, or something else?

And how can I do that without being focused on verification?

What do you guys focus your energy on when you are practising TDD?