答:
Editing placeholders is error prone.

I would go with using a Config file.

Your concern about dependency is valid, however, I don't remember using too many tools that is composed of a single file. So theoretically you are correct, but practically it should be quite OK.

A third option is to make the configuration software write a new tailored version that is specific to the selected options and parameters. This may be harder to write and test of course :)

Title: User Configuration of a Shell Script. Best practices?

Body:
I am writing a shell script with a few variables that should be configured by the user. There will be an installer for downloading and configuring the script, possibly by asking a series of question. The script in question is aimed at other developers.

This can be implemented in a number of ways:

Use placeholders in the script itself and use sed to replace them during installation (something like this: https://stackoverflow.com/questions/415677/how-to-replace-placeholders-in-a-text-file)

Pros: All variable definitions are contained within the script. It's easy to download the script manually and configure the variables for users who prefer an editor over the installer.

Cons: It's hard to reconfigure the variables through the installer once they are in place. Unless I create a more complex regexp which would be prone to errors.

Use a config file, basically another shell script with assignments, and use source to include it. (And probably place it in ~/.scriptname? The main script is copied to /usr/local/bin)

Pros: It's easy to reconfigure the script. Could even add a parameter for doing so from the main script (Would probably work in the first solution as well, but editing a script from itself doesn't sound like a very good idea)

Cons: The script is now dependent on two files and the user is required to run the installer for the configuration file to be created. This can be solved by auto generating a config file if none exists. But locating an external configuration file will still be more cumbersome for users who just want to download the script, edit it, and be done with it.

Also, a few options regarding how the configuration should be managed by the user after the installation:

Git like

$ myscript config server.host example.org
$ myscript config server.proxypath /home/johndoe/proxy
$ myscript config server.httppath /home/johndoe/web

Interactive

$ myscript config

Enter the server hostname: example.org

Enter the path to the proxy on the server: /home/johndoe/proxy

Enter the path to the http directory on the server: /home/johndoe/web

getopts with long options

$ myscript --host example.org --proxypath /home/johndoe/proxy --httppath  /home/johndoe/web

Simple

$ myscript config example.org /home/johndoe/proxy /home/johndoe/web

Are there any other ways of doing this that you would consider?

Any best practices, anything elegant?


问:
not checking in from the project root
Whenever I do a check-in, I always check in from the root of the project... i.e. check in all the files in my working copy, so after the check-in the source control repo contains exactly the same set of files that I just finished testing in my local copy.  I also make sure my source control is set to flag local files that are not under source control.  In general, there are none of these files... if there are, I either add them to source control or mark them as "ignored".  I also check in all my changes together in one check-in.

A lot of colleagues check in much differently.  They carefully select each file to check in, as if they are a master jeweler selecting only the very best gemstones to set into the royal crown, and they check in each one as a separate check-in.  They rely only on their memory to figure out which files need to be checked in, or especially added to source control.

The results are quite predictable... frequent broken builds because they forget to add their new files to source control or forget to check in a changed file (especially changed project files).

I have mentioned this to them and they never seem to change.  When I mentioned it to the team lead he said, "this is just a different way of working".  To which I may respond: What if I want to drive my car with my eyes closed?  Is that just "a different way of driving"?

Am I right in being bothered by this practice?

答:
If broken builds are a problem, I would suggest you evangelize automated builds for your team. If someone checks in a file that breaks the build, an automated build will tell you straight away, rather than waiting for the next guy to come along and find out, spending 15 minutes tracking down the person who's check-in broke the build (because it might not have been the last check-in!) and so on...

If people are checking in files one-at-a-time, you can delay the automated build by a few minutes after it detects a check-in, to allow people to check-in the rest of their files. This is cause for concern as well (question: do they put proper comments in the commit message?), but it's not as big a problem as breaking the build is.

ContentLicense: CC BY-SA 2.5

Title: not checking in from the project root


问:
When, how and why should one upgrade (Java) frameworks?
Short summary as introduction:

We are a small Java web development team, creating applications using various frameworks and libraries like JSF, Hibernate, Seam, all together deployed in JBoss AS.

Initially, the app was put together and some features added to form a showcase to show to potential customers. Some polishing took place, the app got released, it was accepted and working and as time went by, additional features were added, bugs got fixed, new bugs occurred, as it always is.

Due to high bus factors and startup racing, development got a bit out of hand - more and more features were added, not having fully understood the core architecture of the system. It's still working, but there are always pitfalls because the system evolved from where it originated to something else and in the beginning, various shortcuts were taken to speed up development - now all this comes back and development slows down, because workarounds are used and it's fairly hard to introduce new developers into the project.

Now, I'm in the progress of cleaning up and organizing things - installing a bug tracking system, build up a testing/quality culture, thinking of how to do automated testing, code reviews (all that fancy professional stuff we were lacking in the beginning) and doing general refactoring like organizing class hierarchies and functions to make it easier to use stuff. That makes everything a bit better, but there is still a lot to do. As I'm not the person who initially build the system (former lead programmer left) and not that experienced (developing for 2.5 years now, but that's my only 'open world' experience so far), I'm not always sure what to do.

Here's my problem:

Refactoring is always something good and I'm constantly doing it to make things easier, but what puzzles me is when, how and why I should upgrade the basic architecture (that means, libraries the system relies on, application server, database etc.)

Examples:

We are currently using JBoss 4.2.2 - I read somewhere of JBoss 7.1 already out, should I go for that? How can one evaluate this?

We use Seam 2.2 what seems to be a big blocker (does not work on higher JBoss versions, doesn't support JSF2). In addition, I see sources telling me to use JEE features instead of Seam.

Basically, I'm interested in any generic approach for this problems, not only the ones I mentioned in the examples above - as I may stumble over this problems for another library on another system in another time (or someone else may face similar problems).

So, what's the point? Shall I be up to date and use only cutting edge libraries or should i stay with what i have? How do I recognize, the technology I am using is literally a dead horse and jump off? How often should such technology upgrades appear?

And, another question beside the general 'how to do upgrades'-stuff. How do I recognize my piece of software could be called one 'crafted by professionals'?. Is there a Joel test for well-done software besides common programmers sense?

答:
The short answer is that you switch when the effort to not switch exceeds the effort of switching, or when you can foresee that it will soon become so.  That's a very subjective assessment which requires experience, but it's relatively easy to see the extreme cases.

For example, say you estimate one month to switch, but not switching means you can't use a module that's only available in the upgraded version, so you'll have to take two months to implement one from scratch.  The choice is easy.

For another example, if you are spending all your time fixing security vulnerabilities in software that is no longer supported by the vendor, it's a good time to switch.

If you never have meetings where someone says, "This would be a lot better/easier with the new version," then you probably don't need to switch.

The in-between cases are harder to recognize, but it usually feels like building pressure, where sticking with the old version feels more and more limiting.

As far as your well-done software test, your bug tracker provides a good rule of thumb on that.  When you have zero critical defects and your list of non-critical defects is at a reasonable level and steadily shrinking, you can call it 'done.'  You can get a sense of your software architecture quality by the turnaround time for adding new features or fixing bugs.  There's no cut off point that says, "this is professional," but the lower the better.

ContentLicense: CC BY-SA 3.0


问:
Software rewriting alternatives
We have a legacy system to bring up-to-date because:

It uses an unpopular (amoung our users) non-sql database (Btrieve)

Provides only a text interface

Is written in Turbo Pascal (but compiled in free pascal) which is hard to recruit/retain developers to maintain it

To give you an idea of the scale, the code base is 15MB over 756 files.

All the studies I've looked in to such as those listed here suggest it is vastly more expensive to rewrite than to adapt what you have.

If I thought we could encapsulate the legacy stuff behind a web service and then design new client(s), that would be fine. But I'm stuck with this legacy database which 90% of those 756 files reference.

We even attempted replacing the low-level DB code with code to convert to SQL, and while it worked fine, it was too slow because the code is still accessing records one at a time generating far too many SQL statements than it would need. Plus this approach does not allow any improvements in the DB design.

When faced with such an upheaval as replacing the DB that is referenced so heavily in code and the other requirements listed, can it still pay to reuse or are we better off treating the new version as a whole new product and just listing the current systems abilities as requirements (bearing in mind no handy requirements doc exists for the current system).

I know it's too hard to give a definitive answer on this, so just any advice would be appreciated especially if you've experienced a similar situation.

答:
Two issues.

One, the tiger team issue. Usually these developments fail as the old system would be the requirement for the new one, while the old one also changes, it's a Zeno's paradox. Uncle Bob wrote an article about this, but it's also part of several of his talks and perhaps some of his books as well.

Second, the UI issue.

It's not just that people are used to the UI. That's the tip of the iceberg.

For the users, the system IS the UI. That's why it was called the "user interface" at the first place. I don't even really understand how could they hate the underlying database system, as they have nothing to deal with it? Isn't it lying "under" enough?

If the user interface, the behaviour, the data, and the performance stays the same, you could change every bit of the system, the users wouldn't take a notice. You could convert it from Borland Pascal to Turbo C and vice-versa, you could change the server OS from FreeBSD to Solaris, from Windows to Linux, from Intel to PPC, whatever.

And this is good and bad for you. As long, as you keep the UI, you can change the system. If you change the interface, make sure the logic stays the same behind for a while.

(Your only problem will be, that the users don't have a problem with the underlying system: they have a problem with its user interface. Every single user-initiated change request is UI-based, this is what SVN / CVS / git logs show of every system, because that's the language the user speaks.)

It's like refactoring: you either change the code structure, but don't modify behaviour, or you change the behaviour, but don't change code structure. And have automated tests for that.

I don't know how you can test it, usually we used screenscrapers for reaaallly old applications. I've even seen banking frontend which literally typed the results of a form submission into a terminal to the old code. Not joking.

Change one step at a time. Have a hybrid system for a while. Change UI, retain system, change system, retain UI, change UI, retain system, change system, retain UI...

It's good that you have the source. Even if it's Pascal, it makes your life a few billion magnitudes easier.

For one refactor, I collected all input the system got in a half-an hour intensive testing period, and collected all the database changes it was to do. You can read about it here

Perhaps you should collect real system usage, by the use of keyloggers and terminal capture like kibitz or script.

Oh, and pray that your tests cover everything.

Title: Software rewriting alternatives


答:
There are a number of reasons why you might want to upgrade your underlying infrastructure, and you should evaluate each of them as empirically as you can. For example, you might upgrade because:

The vendor is no longer supporting the version you're using

There's an critical bug or security fix

There's a new feature you want to take advantage of

It will increase your velocity

There's a direct capex cost reduction in upgrading (cheaper support license or similar)

These reasons needs to be weighed up agains the cost of upgrading, most of which is spent in testing. This is where TDD / BDD really comes to the fore, especially when combined with a good CI setup.

It means you can "Refactor rapidly without fear"

If you don't have a decent comprehensive test suite in place, it means you're manually testing, which is time consuming and very error prone, raising cost of upgrade.

Title: When, how and why should one upgrade (Java) frameworks?

Body:
Short summary as introduction:

We are a small Java web development team, creating applications using various frameworks and libraries like JSF, Hibernate, Seam, all together deployed in JBoss AS.

Initially, the app was put together and some features added to form a showcase to show to potential customers. Some polishing took place, the app got released, it was accepted and working and as time went by, additional features were added, bugs got fixed, new bugs occurred, as it always is.

Due to high bus factors and startup racing, development got a bit out of hand - more and more features were added, not having fully understood the core architecture of the system. It's still working, but there are always pitfalls because the system evolved from where it originated to something else and in the beginning, various shortcuts were taken to speed up development - now all this comes back and development slows down, because workarounds are used and it's fairly hard to introduce new developers into the project.

Now, I'm in the progress of cleaning up and organizing things - installing a bug tracking system, build up a testing/quality culture, thinking of how to do automated testing, code reviews (all that fancy professional stuff we were lacking in the beginning) and doing general refactoring like organizing class hierarchies and functions to make it easier to use stuff. That makes everything a bit better, but there is still a lot to do. As I'm not the person who initially build the system (former lead programmer left) and not that experienced (developing for 2.5 years now, but that's my only 'open world' experience so far), I'm not always sure what to do.

Here's my problem:

Refactoring is always something good and I'm constantly doing it to make things easier, but what puzzles me is when, how and why I should upgrade the basic architecture (that means, libraries the system relies on, application server, database etc.)

Examples:

We are currently using JBoss 4.2.2 - I read somewhere of JBoss 7.1 already out, should I go for that? How can one evaluate this?

We use Seam 2.2 what seems to be a big blocker (does not work on higher JBoss versions, doesn't support JSF2). In addition, I see sources telling me to use JEE features instead of Seam.

Basically, I'm interested in any generic approach for this problems, not only the ones I mentioned in the examples above - as I may stumble over this problems for another library on another system in another time (or someone else may face similar problems).

So, what's the point? Shall I be up to date and use only cutting edge libraries or should i stay with what i have? How do I recognize, the technology I am using is literally a dead horse and jump off? How often should such technology upgrades appear?

And, another question beside the general 'how to do upgrades'-stuff. How do I recognize my piece of software could be called one 'crafted by professionals'?. Is there a Joel test for well-done software besides common programmers sense?


答: The technologies that you've listed are widely used, it's easy to find documentation for them and people who are proficient with them, so I think there's no real reason to change them. On the other hand I'd recommend to upgrade your frameworks to the latest released versions. I think you will need to do it anyway, sooner or later (if not for new features and compatibility with newer libraries, then to the bugs fixed in new releases), and the earlier you do it, the less tedious this task will be.</p>


问:
Programming with ADD/ADHD
I have diagnosed ADD.  Mild but enough to affect my work:

Easily distracted

Can't concentrate on one project at a time

Addicted to the web

Procrastination

etc.

What strategies do you use to compensate?

One clarification

I have real  ADD.  I was diagnosed with it when I was a child and have wrestled with it all my life.  I am not talking about artificial ADD, which is induced by media overload.

Update

I just read this description ADD/ADHD.  It's a great description, especially for us programming ADDers:

I am like a toolbox,

  with all the tools I will ever need

  lain gently and neatly in the box,

  ready for me to use them.

  The toolbox is translucent

  so I can see them there.

  The key to the toolbox is locked inside of it.

答: I actually have ADHD as well... I find it helps though, let me explain. First and very important is work on one project at a time, yo can multi task on that project but it has to be the same project, so the brain doesn't go to overload. I actually found that people with ADD/ADHD (judging from myself and my friends with it) are great brainstormers. I will sit down to work on something to say make 1 feature, at the end with my mind all over the place it will turn to 10 features, or 7 different implementations of that feature. Very important though is noting, when you mind starts going somewhere else, write down what you're doing. I've noticed by writing your brain starts "hypothesising" on different thing related to the project. I've also noticed that occasional breaks help too, something systematic, for example every hour get up for 5 minutes and get a coffee. Also contrary to the previous statement cut on your stimulants, i.e. coffee, energy drinks, etc. It's hard but will help quite a bit</p>

OwnerDisplayName: lamcro

Title: Programming with ADD/ADHD


问:
What level do I mock when I have function A calling function B which calls the database?
I have created a scenario in which I have two functions, A and B, both are tested, but despite the tests I still injected a rather stupid bug and some data is not getting into the database.  Note that there is no ORM present.  I've written my CRUD operations directly, and I'm paying the price therefor.

In this scenario, I have (perl) something like this:

```<code>sub A {
  ... do a bunch of work ...
  my $res = B( %data );
  ... do a bunch more work ...
}

sub B {
  my ( %data ) = @_;
  ... record data to the database and return a result ...
}
</code>```

What happened, though, is that in my higher-level application and in A itself, I changed the name of one of the fields that goes into %data, but forgot to change it in B.  I have a test for A which stubs/mocks out a lot of the things A does (A needs to meet with a goodly refactoring), including B.  The stub for B verifies that all of the correct parameters, including the correct field names get passed in, and so the test passes.

BUT the test for B verifies the old field names, the real B actually uses the old field names, and that test passes as well.

And, thus, I put into production some code that, because of this oversight, is putting NULLs into the database where I don't want NULLs.

A is clearly too big.  To isolate it, I mock out six different functions, each of which could cause a system state change.

A, and thus the test for A is theoretically unconcerned as to the strategy by which B will store data in the database or even what kind of database B will store data to, so I think the test for A probably should not query the database directly.

But, I changed the format of %data, and I think that the test for A should have detected that I basically changed the API without propagating the change down.

What is a better way to set up a test to catch this case beforehand?

Continue with the isolation strategy for A and B, but also write an integration that tests A --all the way to-> the database?  This would lead to a proliferation of possible test cases, and I'm already having trouble justifying the existing test case proliferation to management (though I know the coverage to be woefully inadequate).

Just write the test for A to query the database, possibly through an abstraction?

Is there something different that would help here?

Ultimately, I took Karl Bielefeldt's suggestion.  I added the data validation code into function B.  I also added the integration test that tests from A all the way to DB.

As far as I can tell, I need to have as many integration tests as I possibly can, verifying that the overall state of the system resources change predictably.  At the same time, I expect I'll still need to mock network resources if I cannot actually get a test network environment.

答:
Continue with the isolation strategy for A and B, but also write an integration that tests A --all the way to-> the database? This would lead to a proliferation of possible test cases, and I'm already having trouble justifying the existing test case proliferation to management (though I know the coverage to be woefully inadequate).

This is your solution.

Having this bug should provide more fodder for management. "If we had integration tests, this would've never been a bug."


问:
User Configuration of a Shell Script. Best practices?
I am writing a shell script with a few variables that should be configured by the user. There will be an installer for downloading and configuring the script, possibly by asking a series of question. The script in question is aimed at other developers.

This can be implemented in a number of ways:

Use placeholders in the script itself and use sed to replace them during installation (something like this: https://stackoverflow.com/questions/415677/how-to-replace-placeholders-in-a-text-file)

Pros: All variable definitions are contained within the script. It's easy to download the script manually and configure the variables for users who prefer an editor over the installer.

Cons: It's hard to reconfigure the variables through the installer once they are in place. Unless I create a more complex regexp which would be prone to errors.

Use a config file, basically another shell script with assignments, and use source to include it. (And probably place it in ~/.scriptname? The main script is copied to /usr/local/bin)

Pros: It's easy to reconfigure the script. Could even add a parameter for doing so from the main script (Would probably work in the first solution as well, but editing a script from itself doesn't sound like a very good idea)

Cons: The script is now dependent on two files and the user is required to run the installer for the configuration file to be created. This can be solved by auto generating a config file if none exists. But locating an external configuration file will still be more cumbersome for users who just want to download the script, edit it, and be done with it.

Also, a few options regarding how the configuration should be managed by the user after the installation:

Git like

$ myscript config server.host example.org
$ myscript config server.proxypath /home/johndoe/proxy
$ myscript config server.httppath /home/johndoe/web

Interactive

$ myscript config

Enter the server hostname: example.org

Enter the path to the proxy on the server: /home/johndoe/proxy

Enter the path to the http directory on the server: /home/johndoe/web

getopts with long options

$ myscript --host example.org --proxypath /home/johndoe/proxy --httppath  /home/johndoe/web

Simple

$ myscript config example.org /home/johndoe/proxy /home/johndoe/web

Are there any other ways of doing this that you would consider?

Any best practices, anything elegant?

答:
What would I expect from a sane program (a shell script or not):

I never ever have to alter the executable to just configure it. This is not an OS kernel.

I can pass any setting using command line. This is a must for every piece of information that does not have a reasonable default. The only exception is a password which needs interactive input.

Optionally, I can pass a setting using an environment variable.

I can write the settings down into a config file, and this file will be used if it is present under a well-known name, or explicitly pointed to using the two methods above.

The config file uses the very same setting names and syntax as command line.


问:
As a professional developer, is it acceptable to not write unit tests?
Just wondering on the pros and cons on TDD/automated unit testing and looking for the community's view on whether it's acceptable for professional developers to write applications without supporting unit tests?</p>

答:
As a professional developer, is it acceptable to not write unit tests?

No.

Without question - This should be one of the first lessons that a fresher learns.
You must develop unit tests to prove that your code works before you tell QA that your code is ready for testing. A failure to do so would inflate costs for the project and lower team morale.

How thorough should these unit tests be?

Here is the litmus test: If QA discovers a bug in your code, will you be comfortable using your unit test(s) to prove your due diligence to your boss?

If your answer is 'No', then you should craft a better unit test (or tests).

If your answer is 'Yes', then your code is ready for verification.

As a professional developer, is it acceptable to not write automated unit tests?

Yes.

Particularly if the time and effort spent writing automated unit tests would outweigh the benefit gained by the test. This includes, but is not restricted to, UI code that can be difficult to mock.

Emphasis: I'm not saying that it is impossible to write automated unit tests for UI code. I'm just saying that, in my experience, it is sometimes difficult to write automated unit tests for some  UI code.


答:
Not every problem can be solved with black box testing.  The problem with end-to-end integration testing is that the number of possible paths through the code is much larger than with unit testing.  It's still good to have integration tests, but it's generally impossible to make them thorough unless your system is very simple.  Therefore, it's likely the next integration failure you have won't be covered by a test unless you've seen it before.

My recommendation is to add some integration tests to make sure you don't make this same exact mistake again, but also to add some data validation inside B and make unit tests for that validation (see assertion for more info).  Check that it isn't passed in any fields it doesn't know about, that all the required fields are passed in, etc.  If the validation adversely affects performance, you can have a flag to turn them off.  So instead of your unit tests catching the bug, the developer who introduces it will see it in his test runs.

Title: What level do I mock when I have function A calling function B which calls the database?

Body:
I have created a scenario in which I have two functions, A and B, both are tested, but despite the tests I still injected a rather stupid bug and some data is not getting into the database.  Note that there is no ORM present.  I've written my CRUD operations directly, and I'm paying the price therefor.

In this scenario, I have (perl) something like this:

```<code>sub A {
  ... do a bunch of work ...
  my $res = B( %data );
  ... do a bunch more work ...
}

sub B {
  my ( %data ) = @_;
  ... record data to the database and return a result ...
}
</code>```

What happened, though, is that in my higher-level application and in A itself, I changed the name of one of the fields that goes into %data, but forgot to change it in B.  I have a test for A which stubs/mocks out a lot of the things A does (A needs to meet with a goodly refactoring), including B.  The stub for B verifies that all of the correct parameters, including the correct field names get passed in, and so the test passes.

BUT the test for B verifies the old field names, the real B actually uses the old field names, and that test passes as well.

And, thus, I put into production some code that, because of this oversight, is putting NULLs into the database where I don't want NULLs.

A is clearly too big.  To isolate it, I mock out six different functions, each of which could cause a system state change.

A, and thus the test for A is theoretically unconcerned as to the strategy by which B will store data in the database or even what kind of database B will store data to, so I think the test for A probably should not query the database directly.

But, I changed the format of %data, and I think that the test for A should have detected that I basically changed the API without propagating the change down.

What is a better way to set up a test to catch this case beforehand?

Continue with the isolation strategy for A and B, but also write an integration that tests A --all the way to-> the database?  This would lead to a proliferation of possible test cases, and I'm already having trouble justifying the existing test case proliferation to management (though I know the coverage to be woefully inadequate).

Just write the test for A to query the database, possibly through an abstraction?

Is there something different that would help here?

Ultimately, I took Karl Bielefeldt's suggestion.  I added the data validation code into function B.  I also added the integration test that tests from A all the way to DB.

As far as I can tell, I need to have as many integration tests as I possibly can, verifying that the overall state of the system resources change predictably.  At the same time, I expect I'll still need to mock network resources if I cannot actually get a test network environment.


问:
Good practice to separate Git Repo from published Repo?
We have a central Git repo from which developers fetch and push changes. They make changes on the default master branch. Our Continuous Integration (CI) tool builds artifacts off this default master branch and is the entity responsible for promoting something we want to be tested to a "UAT" branch (this is in reality done by a build-master person clicking a button on the CI tools web page that will do the promotion). The CI tool is also responsible for promoting code from UAT to the "Production" branch. The purpose of the UAT and Production branches is to capture what was promoted to UAT and to Production. No development occurs on the UAT branch and Production will only contain "development" in the form of infrequent "hot-fixes" as our development/release iterations are very fast (1 week iterations).

If we can do it easily, we'd like to put in a control that will prevent someone mistakenly making development changes to UAT and Production branches directly. One thought is to have a hook on the central server that makes sure that only the CI tool user can make changes to UAT and Production. We also thought we could have a central repo that developers use that only contains the master branch and have a second repo that contains the UAT and Production branches. The CI tool will communicate with both repos-- it will look at the development to repo to see when there are changes and use the second repo to do its promotion to the UAT and Production branches.

Is this what folks typically do (separate repos for purposes of development versus promotion?) Would it be better than the server hook approach?

答: The CI tool needs its own repo anyway in order to maintain a working tree for the builds, right?  May as well just publish that repo read-only for the UAT and production branches.  Some people prefer the hook method because it is more centralized, but the separate repo method is easier to secure, because you can have them on completely separate computers controlled by separate people.  You don't have to worry about who has permissions to change hooks on the developer repo.</p>


问:
How can we make software development best practices more interesting to people without a software background?
Where I work there are a few experienced software developers with a software background, but the majority of developers are physicists or chemists with excellent domain knowledge but limited experience when it comes to developing high quality, maintainable software.  To address this we have started running regular talks and workshops.

What topics do you think we should discuss to help make these people more effective software developers?

In particular we are struggling to gain enthusiasm for these talks as many developers do not see software as an interesting subject.  How could we make these more interesting to people without a software background?

Thanks

答:
I work with very smart networking engineers who are not developers and don't want to be. I can understand that because I don't want to be a networking engineer.

What we've found that works well is for the engineer and I to do team-programming. We're at separate sites, so we get on the phone, open a screen sharing session usually with the screen command, and bust out the code.

We've done that many times and felt it worked really well. I'm understanding how they do their thing better, and the engineer is learning how we write maintainable and tested code.


问:
Do you see an use for "Spreadsheet programming"?
A while ago I stumbled upon the concept of using spreadsheets (I mean cells and formulas not Macro code) as a way to specify programming logic.
The idea is:

create a spreadsheet with a cleanly defined flow of calculations (which sometimes are better suited to the "dataflow" paradigm of spreadsheets instead of procedural or object oriented programming styles)

define input cells

define output cells

compile the whole thing into a stand-alone executable class (or function, procedure, ...)

use it in normal code within a broader software project

use the spreadsheet as source code to be maintained over time

The idea is to use this technique for problems the really fit into the model and that this would lead to naturally well-documented and easy maintainable code.
I am interested in knowing whether you have experienced using the technique and what for.
An example application that came to my mind are insurance tariff calculators, that are typically drafted, created and validated by actuaries on Excel sheets and only later coded (it's a painful process) in some hard-to-maintain programming logic.

答:
which sometimes are better suited to the "dataflow" paradigm of spreadsheets instead of
  procedural or object oriented programming styles

Honestly, I can hardly think of any real-world calculations where this applies. "Dataflow" programming can be easily done a lot of modern programming languages (look at LINQ in the .NET world, or the list processing operators of Perl and Python), and to my experience, that results in much more maintainable code than a bunch of "spreadsheet formulas" with hard-to-maintain cell references.

On the other hand, me and my colleagues have created lots of spreadsheet-based (MS-Excel, to be precise) applications, where Excel was used either as a user-friendly tool for entering input data / creating input masks very quickly, or for creating formatted output, or both. In all those cases, the calculation or processing of that data was not done (or only partially done) by Excel formulas, but by program code, since Excel formulas were not powerful enough or the completely wrong tool (and believe me, we have a lot of knowledge what is possible with Excel formulas and what is not).


答:
There are several things you should do :

refactor the code. Make your functions A and B smaller, with less functionality, and unit test small pieces

add missing integration tests. Obviously you missed some tests, since it was possible to trigger a bug.

add some run-time checks. If certain condition is not met, throw an exception.


答:
The stub for B verifies that all of the correct parameters, including the correct field names get passed in, and so the test passes.

Your best bet for avoiding something like this is getting into the TDD habit. If you had, you'd have realised that you needed a test to fail before you made your change. That test (whether it be a new test or an extension of an existing test) would have been checking your new fields.


问:
strategies to keep tabs of memory leaks in non memory-managed languages
When it comes to non memory managed languages such as C, C++ or Fortran (my case), it becomes increasingly difficult to keep track of memory allocation/deallocation, especially when ownership must be shared. I implemented refcounting for my objects, but this makes it even more complicated as there's no place where an object gets deallocated. Every reference decrement is a potential deallocation point.

So it's now more and more difficult for me to track down memory leaks. I was wondering about some established techniques to deal with memory management in non-memory managed languages, apart from valgrinding your way around.

Edit: I am more interested in active programming strategies (which are general).

答:
I use my own set of wrapper routines for allocation and deallocation, which require each chunk to be identified by a string that identifies the allocation.  For example
 myAlloc(size,"temporary for mumble sort")

In debug mode, every chunk is added to a (potentially large) hashtable, and at exit the remaining leaks are reported along with the strings for the trash.  In nondebug mode, only summary bookkeeping is done.

From this scheme, I get a tripwire in production code that warns of unexpected leaks, and I get detailed, immediate feedback when developing about what is leaking.


问:
Python simulation-scripts architecture
Situation:

I've some scripts that simulate user-activity on desktop. Therefore I've defined a few cases (workflows) and implemented them in Python. I've also written some classes for interacting with the users' software (e.g. web browser etc.).

Problem:

I'm a total beginner in software design / architecture (coding isn't a problem).
How could I structure what I described above?

Providing a library which contains all the workflows as functions, or a separate class/module etc. for each workflow?

I want to keep the the workflows simple. The complexity should be hidden in the classes for interacting with the users' software.

Are there any papers / books I could read about this, or could you provide some tips?

答:
I tend to prefer to represent series of actions as series of statements, which would equate to actual code. That would mean a function with the steps to simulate the activity as method calls on the objects that represent the interface to be interacted with. This seems to be what you describe as having already.

However, if the actions are something that need to be editable by the user or some other part of the system, then you need to have a representation for the steps of the scripts. That sounds very familiar so I'm pretty sure there is a design pattern to do just that. I would suggest looking at the Command, Strategy and Template Method design patterns, as one or more of them might be what you are looking for. If you need a book, those I mentioned are described in the "Gang of Four" book, Design Patterns: Elements of Reusable Object-Oriented Software, which is the book that introduced the concept of design patterns.

Title: Python simulation-scripts architecture


问:
NSNotificationCenter vs. Protocol
I am using MPMoviePlayerController in a project. The loadState of the MPMoviePlayerController object is observed using NSNotificationCenter.

Why did Apple choose NSNotificationCenter in this situation instead of using delegation?

答:
You may have more than one class that is interested in the loadState of the MPMoviePlayerController. A plausible example of this is the fact that Apple may be using the loadState-related notification to do some of their own stuff under the hood. Now you come along and also express interest in the same notification. Using NSNotificationCenter, you both can say "Hey, I want to be notified when the loadState of this player changes".

In the case of a protocol (delegation), it's generally a one-to-one relationship. An object, in your example the player, could only have one delegate. So if Apple needed to know about the loadState, and you needed to learn about the loadState also, one of you would be out of luck!

NSNotificationCenter has what's considered a "loosely coupled" relationship with the object that posts a notification and the object(s) that observes that notification. In delegation, however, the relationship tends to be significantly tighter.

Title: NSNotificationCenter vs. Protocol


问:
Unwritten rules of rewriting another team member's code
We are practicing collective code ownership. To my understanding this means that any developer can change any line of code to add functionality, to refactor, fix bugs or improve designs.

But what about a complete rewriting of code from a developer who is still in the team? Should I ask him first? What is the best practice?

答: Often code is written a certain way for a reason. Communicating the change to the author always works out for the best.</p>


问:
Why the question "give five things you hate about C#" is so difficult to answer during an interview?
In podcast 73, Joel Spolsky and Jeff Atwood discuss, among other subjects, "five things everyone should hate about their favorite programming language":

If you’re happy with your current tool chain, then there’s no reason you need to switch. However, if you can’t list five things you hate about your favorite programming language, then I argue you don’t know it well enough yet to judge. It’s good to be aware of the alternatives, and have a healthy critical eye for whatever it is you’re using.

Being curious, I asked this question to any candidate I interviewed. None of them were able to quote at least one thing they hate about C#¹.

Why? What's so difficult in this question? It is because of the stressful context of the interview that this question is impossible to answer by the interviewees?

Is there something about this question which makes it bad for an interview?

Obviously, it doesn't mean that C# is perfect. I have myself a list of five things I hate about C#:

The lack of variable number of types in generics (similar to params for arguments).

Action<T>,

Action<T1, T2>,

Action<T1, T2, T3>,

       ⁞

Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>

Seriously?!

The lack of support for units of measure, like in F#.

The lack of read only properties. Writing a backing private readonly field every time I want a read only property is boring.

The lack of properties with default values. And yes, I know that I can initialize them in the parameterless constructor and call it from all other constructors. But I don't want to.

Multiple inheritance. Yes, it causes confusion and you don't need it in most cases. It's still useful in some (very rare) cases, and the confusion applies as well (and was solved in C#) to the class which inherits several interfaces which contain methods with the same name.

I'm pretty sure that this list is far from being complete, and there are much more points to highlight, and especially much better ones than mine.

¹ A few people criticized some assemblies in .NET Framework or the lack of some libraries in the framework or criticized the CLR. This doesn't count, since the question was about the language itself, and while I could potentially accept an answer about something negative in the core of .NET Framework (for example something like the fact that there is no common interface for TryParse, so if you want to parse a string to several types, you have to repeat yourself for every type), an answer about JSON or WCF is completely off-topic.

答:
I would imagine that the question is so hard to answer during an interview because it's:

Really unexpected,

Requires a lot of thinking, and a thinking in a very different way from the one used during an interview,

Is hard to answer in general in a short amount of time (unless prepared before the interview).

1. It's unexpected

Unexpected questions are truly hard, especially in a stressful context. Imagine the following dialog during an interview:

‒ What's the difference between HashSet<T> and List<T>?

  ‒ The hashset is optimized in a way that the search for an element is very fast. For example if you're using set.Contains() within a loop lots of times, moving the set from list to hashset may make things faster.

  ‒ How do you create a read only property?

  ‒ I use a field marked as readonly as a backing field for a property which has only a getter.

  ‒ What is the usage of sealed?

  ‒ You use it for classes which must not be inherited.

  ‒ What's the last time you've seen a dentist?

  ‒ What?!

2. It requires a lot of different thinking

When you're asked general interview-type questions, you're using your memory to recall what you've learnt from books or from your practice about the language and the framework. You may think a bit in order to find an answer, but not too much.

On the other hand, the question about the five things you hate requires a deeper thinking. You can't just recall something you've learnt from books, and you can't find anything by analogy. Instead of being passive, you have to be critic and find what could be unpleasant in the language you use.

3. It requires time

Frankly, I have my list of five (actually more) things I hate about C#, but I thought about it over a long period of time. A few things are from the .NET Framework 2 era; most issues I listed for .NET Framework 2 are no longer valid because they were removed, some with LINQ and all this functional programming stuff, others with dynamic programming. I'm not sure if, without preparing this question, I would be able to find all the five elements during an interview.


答:
I think in his round about way he's saying; if you think it is broken you probably don't understand why it is as it is. There may be a hole in your knowledge.

Ironically, interviewers who think they are quoting "the great Joel" by using that as an interview question are probably rather missing the point.

Title: Why the question "give five things you hate about C#" is so difficult to answer during an interview?

Body:
In podcast 73, Joel Spolsky and Jeff Atwood discuss, among other subjects, "five things everyone should hate about their favorite programming language":

If you’re happy with your current tool chain, then there’s no reason you need to switch. However, if you can’t list five things you hate about your favorite programming language, then I argue you don’t know it well enough yet to judge. It’s good to be aware of the alternatives, and have a healthy critical eye for whatever it is you’re using.

Being curious, I asked this question to any candidate I interviewed. None of them were able to quote at least one thing they hate about C#¹.

Why? What's so difficult in this question? It is because of the stressful context of the interview that this question is impossible to answer by the interviewees?

Is there something about this question which makes it bad for an interview?

Obviously, it doesn't mean that C# is perfect. I have myself a list of five things I hate about C#:

The lack of variable number of types in generics (similar to params for arguments).

Action<T>,

Action<T1, T2>,

Action<T1, T2, T3>,

       ⁞

Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>

Seriously?!

The lack of support for units of measure, like in F#.

The lack of read only properties. Writing a backing private readonly field every time I want a read only property is boring.

The lack of properties with default values. And yes, I know that I can initialize them in the parameterless constructor and call it from all other constructors. But I don't want to.

Multiple inheritance. Yes, it causes confusion and you don't need it in most cases. It's still useful in some (very rare) cases, and the confusion applies as well (and was solved in C#) to the class which inherits several interfaces which contain methods with the same name.

I'm pretty sure that this list is far from being complete, and there are much more points to highlight, and especially much better ones than mine.

¹ A few people criticized some assemblies in .NET Framework or the lack of some libraries in the framework or criticized the CLR. This doesn't count, since the question was about the language itself, and while I could potentially accept an answer about something negative in the core of .NET Framework (for example something like the fact that there is no common interface for TryParse, so if you want to parse a string to several types, you have to repeat yourself for every type), an answer about JSON or WCF is completely off-topic.


答:
The very premise of this question raises a number of concerns for me that I don't think any of the existing answers are adequately trying to address. Let me ask some follow-up questions here:

Are you absolutely, positively certain that you are talking about rewriting and not refactoring? By definition, changes to code style or structure that result in an improved (or simply different) implementation without changes to the external behaviour is a refactor, not a rewrite. Breaking a monolithic 500-line routine into a set of 50 subroutines may involve writing quite a bit of new code, but it is not a rewrite. The term rewrite implies throwing away an entire product or feature and starting over from scratch; it is not something to be taken lightly.

If the original code's behaviour is so wrong, or the implementation is so buggy as to require a full-fledged rewrite, why was it not caught by your team's process and addressed in its proper context (i.e. technically rather than socially)? Bad or questionable code ought to be exposed quickly on a healthy team via tests, code reviews, design reviews, etc. Do you have these?

Is the manager/tech lead aware of the problem, and if not, why not? No matter what kind of process you have, code quality is ordinarily the development manager's responsibility. He or she is the first person you should be asking - obviously not in the context of "so and so wrote crap code" but simply "I think I see a major problem here, can we talk about a rewrite?" If it doesn't warrant this type of discussion, then maybe it doesn't warrant a rewrite either?

If the size and scope of the offending code is large enough to warrant serious discussion of a rewrite, why is it exclusively owned by one developer? Most if not all of the times when I've seen code and thought "rewrite", it's been trampled on by a dozen different people and the badness is a direct result of the accumulation of style inconsistencies, mistaken or altered assumptions, and good old-fashioned hacks. Code grows thorns over time precisely because of its shared ownership.

My point here is, it's strange that one person would own such a large swath of code in an environment that supposedly practices collective ownership. Are other people afraid to touch this developer's code? Are they afraid to bring up the subject? Maybe there is in an underlying problem with your group dynamic, or with this developer specifically; if there is, don't ignore it. Or, alternatively, perhaps it is your first time working on this project, and if so, why are you thinking about a rewrite so early in the game? Something about the situation doesn't seem to add up for me.

The question states, in the first paragraph, any developer can change any line of code to add functionality, to refactor, fix bugs or improve designs. Will a rewrite not do these things? Or will it do something extra - and if so, what? Fundamentally, what are your reasons for wanting to do a rewrite, and how sure are you that they'll benefit the product or the team? You don't need to answer for me, but you'd better have some objective points to make if and when you choose to discuss it with the team.

I truly feel that this question entails a huge amount of context and should not be answered without a very clear understanding of that context. The "correct" answer completely depends on your team, your product, your organization, your personality, your process, the scope of the original code, the scope of the changes, and so on and so forth. This is, IMO, an issue that you absolutely need to take up with your team, not on an online Q&A site.

Title: Unwritten rules of rewriting another team member's code

Body:
We are practicing collective code ownership. To my understanding this means that any developer can change any line of code to add functionality, to refactor, fix bugs or improve designs.

But what about a complete rewriting of code from a developer who is still in the team? Should I ask him first? What is the best practice?


答:
I'd suggest that part of the problem is fear of giving a bad answer -- you say you hate X, interviewer loves X or thinks your reason for hating X is idiotic, saying that you think it's fine may seem the less controversial option.

It's also probably something that most people haven't really given a lot of thought about; they have current problems and past problems, past problems that were caused by the langauge are over with and so people mainly think of the solution and not the problem as that was more significant, and few will have a current problem caused by the language.


答:
If I would have to guess:

Some programmers lack diverse language exposure. It's hard to see things wrong with the language when you don't know that better things exist.

Some programmers are mere code monkeys. They barely analyze the problems in front of them, let alone something like how their programming language could be better.

Few people are particularly critical. They see benefits and features, not shortcomings. It is hard for them to shift into that mode of thinking if the interview isn't going that way.

At least around here, being overly critical is seen as a fatal personality flaw. Instead of being 'that insightful developer that is always looking for better ways of doing things' (like some areas I've lived), they are 'that asshole that hates everything'. Even people who can think of things they hate in the language might defer in an interview setting to seem less acerbic.


答:
For an interview I would ask for only 1 or 2, but I agree, if you can't name any limitations of the tool you use, then you probably don't know it very well. We ask this exact question about SSIS and it really helps separate the wheat from the chaff; everyone we have hired who answered this question well turned into a great employee. We need people who have actaul advanced knowledge not someone who has looked at it a couple of times. And I'll bet that is what you want too.

I think it is a valid question and the fact that so many couldn't answer it is just an example of how poor many of the candidates for jobs really are. If someone isn't analytical enough to be able to figure out some limtitations of the tool, how are they ever going to be analytical enought to solve difficult programming problems?


问:
Developing an iOS app for a single device - licensing issue
I'm developing an iOS app for a museum as a freelancer. It's a very simple video player, to be installed on a single iPad that will be part of a permanent exhibition, basically acting as a kiosk. It turns out the iPad is the ideal device for that if you're looking for a small and affordable touchscreen.

The problem is: as far as I can tell, none of the Apple Developer Program options available will allow me to distribute an app like that. The relevant options are (from the link above):

iOS Developer Program ($99/year)
Select this program if you would like to distribute apps on the App Store as an individual, sole proprietor, company, organization, government entity or educational institution.

iOS Developer Enterprise Program ($299/year)
Select this program if you would like to develop proprietary apps for internal distribution within your company, organization, government entity or educational institution.

The regular program requires distribution through the App Store. The Enterprise version is for internal distribution within my own organization. Neither is the case here! It seems like I'm doomed to violate Apple's terms of service (and I can think of at least two ways of doing that: jailbreaking, or changing the iPad's date so it won't know the provisioning profile expired).

Is that really so, or did I get the descriptions wrong? Has anyone here been in a similar situation?

答: Could you just link to a YouTube Video or Vimeo link? Then just pin the URL to the ipad's homepage so that it opens in fullscreen?</p>


问:
Database-stored configuration management
Developing database-backed software, often one finds it convenient to store stuff in the database which one might traditionally express in code, but which is useful to store in the database (so that it can be changed without requiring a reload of the application).

For instance, one might have processes which send automated email using a template; it makes sense to store this template in the database, so that the text can be tweaked by the users without having to change the code/redeploy/etc.

However, these templates are "important"- they are required for the correct operation of the system, and for instance, if they become malformed or missing, the underlying functionality would probably stop working. As they live now in the database, they don't outside version control- you might add audit tables to have change history about this information, but revisions/etc. are separate and independent from your main code's revisions.

How do you handle this kind of stuff? Not putting this kind of stuff in the database and make changes go through development/change control/deployment cycles? Or something else?

答:
Many systems can be broken just as easily with bad configuration settings as with bad source/logic: Config is source (or at least just as important), so configuration settings should be stored under version control just like source/logic.

Common automation mechanisms can be used to synchronise production systems with configuration and source changes.

For example:

Keep code & config that is currently in production in a particular area of the repository. (Call it "prod", and place restrictions on who can commit to that location).

To change configuration, make the changes and commit the modified files to prod. Your development process will probably dictate some level of testing before the changes are actually applied to prod.

Once this happens, let your continuous integration system pull the files back out of prod, and (after some automated checks have been performed) push the changed configuration out to the actual production system. A database may well be the mechanism that is used to change configuration without restarts.

The important thing is that automation is used to ensure that the "prod" branch in the repository holds the code and the configuration that is really in production at any one time. (That way, if anything goes wrong, you will not be led astray by out-of-date or inconsistent config and/or source files).

For your particular example, I would be tempted to carefully define the extent to which customers can customize or otherwise modify the functionality of your system. People are fiendishly clever at finding novel ways to stretch a technology beyond the intentions of its creator.

ContentLicense: CC BY-SA 4.0


问:
how a pure functional programming language manage without assignment statements?
When reading the famous SICP, I found the authors seem rather reluctant to introduce the assignment statement to Scheme in Chapter 3. I read the text and kind of understand why they feel so.

As Scheme is the first functional programming language I ever know something about, I am kind of surprised that there are some functional programming languages (not Scheme of course) can do without assignments.

Let use the example the book offers,the bank account example. If there is no assignment statement, how can this be done?How to change the balance variable? I ask so because I know there are some so-called pure functional languages out there and according to the Turing complete theory, this must can be done too.

I learned C, Java, Python and use assignments a lot in every program I wrote. So it's really an eye-opening experience. I really hope someone can briefly explain how assignments are avoided in those functional programming languages and what profound impact (if any) it has on these languages.

The example mentioned above is here:

```<code>(define (make-withdraw balance)
    (lambda (amount)
        (if (>= balance amount)
            (begin (set! balance (- balance amount))
                balance)
            "Insufficient funds")))
</code>```

This changed the balance by set!. To me it looks a lot like a class method to change the class member balance.

As I said, I am not familiar with functional programming languages, so if I said something wrong about them, feel free to point out.

答:
It's not possible making a program 100% functional if it is supposed to do anything useful. (If side effects are not needed then the whole think could have been reduced to a constant compile time) Like the withdraw-example you can make most of the procedures functional but eventually you'll need procedures that has side effects (input from user, output to console). That said you can make most of your code functional and that part will be easy to test, even automatically. Then you make some imperative code to do the input/output/database/... which would need debugging, but keeping most of the code clean it won't be too much work.
I'll use your withdraw-example:

```<code>(define +no-founds+ "Insufficient funds")

;; functional withdraw
(define (make-withdraw balance amount)
    (if (>= balance amount)
        (- balance amount)
        +no-founds+))

;; functional atm loop
(define (atm balance thunk)
  (let* ((amount (thunk balance))
         (new-balance (make-withdraw balance amount)))
    (if (eqv? new-balance +no-founds+)
        (cons +no-founds+ '())
        (cons (list 'withdraw amount 'balance new-balance) (atm new-balance thunk)))))

;; functional balance-line -> string
(define (balance->string x)
  (if (eqv? x +no-founds+)
      (string-append +no-founds+ "\n")
      (if (null? x)
          "\n"
          (let ((first-token (car x)))
            (string-append
             (cond ((symbol? first-token) (symbol->string first-token))
                   (else (number->string first-token)))
             " "
             (balance->string (cdr x)))))))

;; functional thunk to test
(define (input-10 x) 10) ;; define a purly functional input-method

;; since all procedures involved are functional
;; we expect the same result every time.
;; we use this to test atm and make-withdraw
(apply string-append (map balance->string (atm 100 input-10)))

;; no program can be purly functional in any language.
;; From here on there are imperative dirty procedures!

;; A procedure to get input from user is needed.
;; Side effects makes it imperative
(define (user-input balance)
  (display "You have $")
  (display balance)
  (display " founds. How much to withdraw? ")
  (read))

;; We need a procedure to print stuff to the console
;; as well. Side effects makes it imperative
(define (pretty-print-result x)
  (for-each (lambda (x) (display (balance->string x))) x))

;; use imperative procedure with atm.
(pretty-print-result (atm 100 user-input))
</code>```

It is possible to do the same in almost any language and produce the same results (less bugs), though you might have to set temporary variables within a procedure and even mutate stuff, but that doesn't matter to much as long as the procedure actually acts functional (the parameters alone determines the result). I belive you become a better programmer at any language after you have programmed a little LISP :)

Body:
It's not possible making a program 100% functional if it is supposed to do anything useful. (If side effects are not needed then the whole think could have been reduced to a constant compile time) Like the withdraw-example you can make most of the procedures functional but eventually you'll need procedures that has side effects (input from user, output to console). That said you can make most of your code functional and that part will be easy to test, even automatically. Then you make some imperative code to do the input/output/database/... which would need debugging, but keeping most of the code clean it won't be too much work.
I'll use your withdraw-example:

(define +no-founds+ "Insufficient funds")

;; functional withdraw
(define (make-withdraw balance amount)
    (if (>= balance amount)
        (- balance amount)
        +no-founds+))

;; functional atm loop
(define (atm balance thunk)
  (let* ((amount (thunk balance))
         (new-balance (make-withdraw balance amount)))
    (if (eqv? new-balance +no-founds+)
        (cons +no-founds+ '())
        (cons (list 'withdraw amount 'balance new-balance) (atm new-balance thunk)))))

;; functional balance-line -> string
(define (balance->string x)
  (if (eqv? x +no-founds+)
      (string-append +no-founds+ "\n")
      (if (null? x)
          "\n"
          (let ((first-token (car x)))
            (string-append
             (cond ((symbol? first-token) (symbol->string first-token))
                   (else (number->string first-token)))
             " "
             (balance->string (cdr x)))))))

;; functional thunk to test
(define (input-10 x) 10) ;; define a purly functional input-method

;; since all procedures involved are functional
;; we expect the same result every time.
;; we use this to test atm and make-withdraw
(apply string-append (map balance->string (atm 100 input-10)))

;; no program can be purly functional in any language.
;; From here on there are imperative dirty procedures!

;; A procedure to get input from user is needed.
;; Side effects makes it imperative
(define (user-input balance)
  (display "You have $")
  (display balance)
  (display " founds. How much to withdraw? ")
  (read))

;; We need a procedure to print stuff to the console
;; as well. Side effects makes it imperative
(define (pretty-print-result x)
  (for-each (lambda (x) (display (balance->string x))) x))

;; use imperative procedure with atm.
(pretty-print-result (atm 100 user-input))

It is possible to do the same in almost any language and produce the same results (less bugs), though you might have to set temporary variables within a procedure and even mutate stuff, but that doesn't matter to much as long as the procedure actually acts functional (the parameters alone determines the result). I belive you become a better programmer at any language after you have programmed a little LISP :)


问:
What are the practical ways to implement the SRP?
Simply what are the practical techniques people use to check if a class violates the single responsibility principle?

I know that a class should have only one reason to change, but that sentence is somewhat lacking a practical way to really implement that.

The only way I found is to use the sentence "The ......... should ......... itself." where the first space is the class name and the later is the method (responsibility) name.

However, sometimes it's hard to figure out if a responsibility really violates the SRP.

Are there more ways to check for the SRP?

Note:

The question is not about what the SRP means, but rather a practical methodology or a series of steps to check and implement the SRP.

UPDATE

I have added a sample class that clearly violates the SRP. It would be great if people could use it as an example to explain how they approach the single responsibility principle.

The example is from here.

答:
The SRP states, in no uncertain terms, that a class should only ever have one reason to change.

Deconstructing the "report" class in the question, it has three methods:

printReport

getReportData

formatReport

Ignoring the redundant Report being used in every method, it is easy to see why this violates the SRP:

The term "print" implies some kind of UI, or an actual printer. This class therefore contains some amount of UI or presentation logic. A change to the UI requirements will necessitate a change to the Report class.

The term "data" implies a data structure of some kind, but doesn't really specify what (XML? JSON? CSV?). Regardless, if the "contents" of the report ever change, then so will this method. There is coupling to either a database or a domain.

formatReport is just a terrible name for a method in general, but I'd assume by looking at it that it once again has something to do with the UI, and probably a different aspect of the UI than printReport. So, another, unrelated reason to change.

So this one class is possibly coupled with a database, a screen/printer device, and some internal formatting logic for logs or file output or whatnot. By having all three functions in one class, you're multiplying the number of dependencies and tripling the probability that any dependency or requirement change will break this class (or something else that depends on it).

Part of the problem here is that you've picked a particularly thorny example. You should probably not have a class called Report, even if it only does one thing, because... what report? Aren't all "reports" completely different beasts, based on different data and different requirements? And isn't a report something that's already been formatted, either for screen or for print?

But, looking past that, and making up a hypothetical concrete name - let's call it IncomeStatement (one very common report) - a proper "SRPed" architecture would have three types:

IncomeStatement - the domain and/or model class that contains and/or computes the information that appears on formatted reports.

IncomeStatementPrinter, which would probably implement some standard interface like IPrintable<T>. Has one key method, Print(IncomeStatement), and maybe some other methods or properties for configuring print-specific settings.

IncomeStatementRenderer, which handles screen rendering and is very similar to the printer class.

You could also eventually add more feature-specific classes like IncomeStatementExporter / IExportable<TReport, TFormat>.

This is made significantly easier in modern languages with the introduction of generics and IoC containers. Most of your application code does not need to rely on the specific IncomeStatementPrinter class, it can use IPrintable<T> and thus operate on any kind of printable report, which gives you all of the perceived benefits of a Report base class with a print method and none of the usual SRP violations. The actual implementation need only be declared once, in the IoC container registration.

Some people, when confronted with the above design, respond with something like: "but this looks like procedural code, and the whole point of OOP was to get us -away- from the separation of data and behavior!" To which I say: wrong.

The IncomeStatement is not just "data", and the aforementioned mistake is what causes a lot of OOP folks to feel they are doing something wrong by creating such a "transparent" class and subsequently start jamming all kinds of unrelated functionality into the IncomeStatement (well, that and general laziness). This class may start out as just data but, over time, guaranteed, it will end up as more of a model.

For example, a real income statement has total revenues, total expenses, and net income lines. A properly-designed financial system will most likely not store these because they are not transactional data - in fact, they change based on the addition of new transactional data. However, the calculation of these lines is always going to be exactly the same, no matter whether you are printing, rendering, or exporting the report. So your IncomeStatement class is going to have a fair amount of behaviour to it in the form of getTotalRevenues(), getTotalExpenses(), and getNetIncome() methods, and probably several others. It is a genuine OOP-style object with its own behaviour, even if it doesn't really seem to "do" much.

But the format and print methods, they have nothing to do with the information itself. In fact, it's not too unlikely that you'll want to have several implementations of these methods, e.g. a detailed statement for management and a not-so-detailed statement for the shareholders. Separating these independent functions out into different classes gives you the ability to choose different implementations at runtime without the burden of a one-size-fits all print(bool includeDetails, bool includeSubtotals, bool includeTotals, int columnWidth, CompanyLetterhead letterhead, ...) method. Yuck!

Hopefully you can see where the above, massively-parameterized method goes wrong, and where the separate implementations go right; in the single-object case, every time you add a new wrinkle to the printing logic, you have to change your domain model (Tim in finance wants page numbers, but only on the internal report, can you add that?) as opposed to just adding a configuration property to one or two satellite classes instead.

Implementing the SRP properly is about managing dependencies. In a nutshell, if a class already does something useful, and you are considering adding another method that would introduce a new dependency (such as a UI, a printer, a network, a file, whatever), don't. Think about how you could add this functionality in a new class instead, and how you could make this new class fit into your overall architecture (it's pretty easy when you design around dependency injection). That is the general principle/process.

Side note: Like Robert, I patently reject the notion that an SRP-compliant class should have only one or two state variables. Such a thin wrapper could rarely be expected to do anything truly useful. So don't go overboard with this.


答:
It comes down to like you said lack of in depth experience with C# and/or lack of exposure to other languages. I've interviewed a number of developers who considered themselves senior who couldn't answer some questions that even a light scratch at the surface of C# should have revealed to them.

Without enough digging, you're not going to reach the limits of the language and wish that they were gone. My top five in case anyone's wondering

Immutable objects require a lot of ceremony to create (as opposed to a functional language where objects are immutable by default).

Metaprogramming is difficult to do. Compare type emit to Lisp macros. (Compiler Services will help a lot with this going forward).

Extension methods are great...extension properties and extension operators (specifically implicit and explicit operators) would be better.

Explicit Casts are resolved at compile time instead of run-time.

No Sequence Matching it's so much cleaner than function overloading.


答:
They might be reluctant to answer because they might be under the impression that if they can list 5 things they hate about a language the interviewer might turn round and say 'Oh, we're looking for C# 'ninjas' and you don't seem to like the language', or 'Why did you apply for the job if you don't like the language?'.

Interviewees are under a lot of pressure to remain positive during interviews.


答:
Yes, however I think of it more as "spreadsheet testing" rather than "spreadsheet programming". For example, recently I was working on a feature for our project that involves performing a calculation on large numbers of database records. The calculation was relatively simple yet important and so needed particular testing attention. Furthermore, the formula we were using required a small amount of adaptation to be applicable to our situation.

I ran through some calculations by hand to write my unit tests, while the tester I was working with created a spreadsheet like you have described for use in his end-to-end tests. Due to the adaptation of the source formula we didn't have any independent test data to compare against, therefore the spreadsheet provided a kind of "double-entry bookkeeping" style check that gave us confidence that the code was correct.

So yes, I see this technique as being very useful as a source of test data for cases where the calculations involved are easy to implement in a spreadsheet but are otherwise required to be implemented in code. However, such a spreadsheet shouldn't be used to "specify programming logic" per se, but merely the required end result(s).

Title: Do you see an use for "Spreadsheet programming"?

Body:
A while ago I stumbled upon the concept of using spreadsheets (I mean cells and formulas not Macro code) as a way to specify programming logic.
The idea is:

create a spreadsheet with a cleanly defined flow of calculations (which sometimes are better suited to the "dataflow" paradigm of spreadsheets instead of procedural or object oriented programming styles)

define input cells

define output cells

compile the whole thing into a stand-alone executable class (or function, procedure, ...)

use it in normal code within a broader software project

use the spreadsheet as source code to be maintained over time

The idea is to use this technique for problems the really fit into the model and that this would lead to naturally well-documented and easy maintainable code.
I am interested in knowing whether you have experienced using the technique and what for.
An example application that came to my mind are insurance tariff calculators, that are typically drafted, created and validated by actuaries on Excel sheets and only later coded (it's a painful process) in some hard-to-maintain programming logic.


问:
What do you look at first: the code or the design?
If you've just been introduced to a new project, what's the first thing you look for to get an idea of how it works?

Do you look for the design first?  If there is a design, what do you look for in it? Class diagrams or deployment diagrams or sequence diagrams or something else?

Or do you go straight for the code? If so, how do you understand how the different layers interact?

答:
well, what is "the design"? a README? a uml diagram? you can do a design document halfway (and most do), you can't code halfway

any design is simply going to be an opinion, whereas the code is the fact

i'll only refer to secondary documents when i can't understand the reasoning of the code

reading code is an essential skill for a developer. you might as well learn it now, you won't get to see much useful documentation during your career anyway


问:
Extreme Programming - documenting implementation?
In extreme programming methodology, what artifacts/ can be used to document the implementation?

I have used an activity diagram to document the design steps for each activity. I have read that for XP, the implementation chapter is the code itself.

I am developing an android application which consists of the GUI and java coding.

答:
By core definition of XP methodology, there is a lack of design specification or documentations. Reference below is from Wiki - Extreme programming.

```<code>    Critics have noted several potential drawbacks,[5] including problems with unstable
requirements, no documented compromises of user conflicts, and a lack of an overall
design specification or document.
</code>```

This approach has a number of critics and one of them:

```<code>Can increase the risk of scope creep due to the lack of detailed requirements documentation
</code>```

Supporters of XP stress the following: Coders like coding, not documenting, and coders like seeing code they've written work.

We are creating some documentation (UML snippets, method signatures and other remarks) and include some of them in unit tests. However, project have to document the code at some time, because it's how customers actually use those features that you thought up. It'd be selfish just to code and never document or comment on how the software works.

Any documentation is tough for a programmer since he can never explain the software in less than ten hundreds of words. Thus, option of having Video documents that records design approach and use cases, as well as diagrams to show interaction between components can be done with less time and more fun.

Body:
By core definition of XP methodology, there is a lack of design specification or documentations. Reference below is from Wiki - Extreme programming.

    Critics have noted several potential drawbacks,[5] including problems with unstable
requirements, no documented compromises of user conflicts, and a lack of an overall
design specification or document.

This approach has a number of critics and one of them:

Can increase the risk of scope creep due to the lack of detailed requirements documentation

Supporters of XP stress the following: Coders like coding, not documenting, and coders like seeing code they've written work.

We are creating some documentation (UML snippets, method signatures and other remarks) and include some of them in unit tests. However, project have to document the code at some time, because it's how customers actually use those features that you thought up. It'd be selfish just to code and never document or comment on how the software works.

Any documentation is tough for a programmer since he can never explain the software in less than ten hundreds of words. Thus, option of having Video documents that records design approach and use cases, as well as diagrams to show interaction between components can be done with less time and more fun.


答:
One possible implementation (in Java).  I took liberties with the return types but over all I think it answers the question.  TBH I don't think the interface to the Report class is that bad, though a better name might be in order.  I left out guard statements and assertions for brevity.

EDIT:  Also notice that the class is immutable.  So once it is created you can't change anything.  You could add a setFormatter() and a setPrinter() and not get into too much trouble.  The key, IMHO, is to not change the raw data after instantiation.

```<code>public class Report
{
    private ReportData data;
    private ReportDataDao dao;
    private ReportFormatter formatter;
    private ReportPrinter printer;

    /*
     *  Parameterized constructor for depndency injection,
     *  there are better ways but this is explicit.
     */
    public Report(ReportDataDao dao,
        ReportFormatter formatter, ReportPrinter printer)
    {
        super();
        this.dao = dao;
        this.formatter = formatter;
        this.printer = printer;
    }

    /*
     * Delegates to the injected printer.
     */
    public void printReport()
    {
        printer.print(formatReport());
    }

    /*
     * Lazy loading of data, delegates to the dao
     * for the meat of the call.
     */
    public ReportData getReportData()
    {
        if (reportData == null)
        {
            reportData = dao.loadData();
        }
        return reportData;
    }

    /*
     * Delegate to the formatter for formatting
     * (notice a pattern here).
     */
    public ReportData formatReport()
    {
        formatter.format(getReportData());
    }
}
</code>```

Title: What are the practical ways to implement the SRP?

Body:
Simply what are the practical techniques people use to check if a class violates the single responsibility principle?

I know that a class should have only one reason to change, but that sentence is somewhat lacking a practical way to really implement that.

The only way I found is to use the sentence "The ......... should ......... itself." where the first space is the class name and the later is the method (responsibility) name.

However, sometimes it's hard to figure out if a responsibility really violates the SRP.

Are there more ways to check for the SRP?

Note:

The question is not about what the SRP means, but rather a practical methodology or a series of steps to check and implement the SRP.

UPDATE

I have added a sample class that clearly violates the SRP. It would be great if people could use it as an example to explain how they approach the single responsibility principle.

The example is from here.

Body:
One possible implementation (in Java).  I took liberties with the return types but over all I think it answers the question.  TBH I don't think the interface to the Report class is that bad, though a better name might be in order.  I left out guard statements and assertions for brevity.

EDIT:  Also notice that the class is immutable.  So once it is created you can't change anything.  You could add a setFormatter() and a setPrinter() and not get into too much trouble.  The key, IMHO, is to not change the raw data after instantiation.

public class Report
{
    private ReportData data;
    private ReportDataDao dao;
    private ReportFormatter formatter;
    private ReportPrinter printer;

    /*
     *  Parameterized constructor for depndency injection,
     *  there are better ways but this is explicit.
     */
    public Report(ReportDataDao dao,
        ReportFormatter formatter, ReportPrinter printer)
    {
        super();
        this.dao = dao;
        this.formatter = formatter;
        this.printer = printer;
    }

    /*
     * Delegates to the injected printer.
     */
    public void printReport()
    {
        printer.print(formatReport());
    }

    /*
     * Lazy loading of data, delegates to the dao
     * for the meat of the call.
     */
    public ReportData getReportData()
    {
        if (reportData == null)
        {
            reportData = dao.loadData();
        }
        return reportData;
    }

    /*
     * Delegate to the formatter for formatting
     * (notice a pattern here).
     */
    public ReportData formatReport()
    {
        formatter.format(getReportData());
    }
}


问:
Unit test coding standards
Usually when talking about coding standards we refer to the code of the program itself, but what about the unit tests? Are there certain coding standards guidelines that are unique to unit tests? What are they? </p>

答:
Somewhat similar to what Farmboy has already mentioned,
My method name format

```<code> <MethodName>Should<actionPerformed>When<Condition>
</code>```

e.g

```<code> GetBalanceShouldReturnAccountBalance() {
</code>```

Title: Unit test coding standards

Body:
Somewhat similar to what Farmboy has already mentioned,
My method name format

 <MethodName>Should<actionPerformed>When<Condition>

e.g

 GetBalanceShouldReturnAccountBalance() {


问:
Which programming designs leads to more problems?
As a fresh programmer, one of the first thing for me to learn was to learn language and its syntax. Now my next training issue is to design my code heirarchy in such a way it is simple to maintain over time. One example I just encountered is below. It is in VBA for Excel but the concept extends to other languages too.

As someone with very little experience, it seems to me that the 2nd option is much clearer and I should use that style. However, I know sometimes that to a beginner programmer what seems like a relatively benign choice can end up hurting their development in the long run.

Are either of these two styles the better? I am not talking about personal 'stylistic' choices, I am talking about which one leads to more problems down the line, likely through over-complicating things.

```<code>For ws in Worksheets
    remove duplicates
    append remaining data to separate workbook
Next ws
</code>```

versus

```<code>For ws in Worksheets
    remove duplicates
Next ws

For ws in Worksheets
    append remaining data to separate workbook
Next ws
</code>```

Thankyou!

EDIT: By the way, it is not important if the less-readable design style is faster. A small increase in performance is not worth a loss of readability for my purposes at the moment.

答:
I'm not terribly familiar with VBA, but at a glance it seems this syntax would be preferable in every way:

```<code>For ws in Worksheets
    remove duplicates
    append remaining data to separate workbook
Next ws
</code>```

For one thing, it seems quite readable to me.
For another, you're doing one loop, not two.

Body:
I'm not terribly familiar with VBA, but at a glance it seems this syntax would be preferable in every way:

For ws in Worksheets
    remove duplicates
    append remaining data to separate workbook
Next ws

For one thing, it seems quite readable to me.
For another, you're doing one loop, not two.


答:
When programming, you want to go with the simplest approach possible while still having sufficient robustness.

The former approach is simpler, while the latter is more robust. If you have good reason to believe that the second action might potentially be decoupled with the first one in the future, then go for the latter. Otherwise, go with the simpler approach.

Title: Which programming designs leads to more problems?

Body:
As a fresh programmer, one of the first thing for me to learn was to learn language and its syntax. Now my next training issue is to design my code heirarchy in such a way it is simple to maintain over time. One example I just encountered is below. It is in VBA for Excel but the concept extends to other languages too.

As someone with very little experience, it seems to me that the 2nd option is much clearer and I should use that style. However, I know sometimes that to a beginner programmer what seems like a relatively benign choice can end up hurting their development in the long run.

Are either of these two styles the better? I am not talking about personal 'stylistic' choices, I am talking about which one leads to more problems down the line, likely through over-complicating things.

```<code>For ws in Worksheets
    remove duplicates
    append remaining data to separate workbook
Next ws
</code>```

versus

```<code>For ws in Worksheets
    remove duplicates
Next ws

For ws in Worksheets
    append remaining data to separate workbook
Next ws
</code>```

Thankyou!

EDIT: By the way, it is not important if the less-readable design style is faster. A small increase in performance is not worth a loss of readability for my purposes at the moment.


答:
I think it's difficult because of the word five.  And to a lesser degree, because of the word hate.

Five?  What if you only come up with four?  Have you failed to answer the question?  What if you have more than five?  Now, on the spot, you have to figure out which of those are the best five to use.

Hate is a very negative word.  It's the kind of negativity that people are told to avoid in interviews.  Moreover, I think it would sound odd to a lot of people to have that many things they "hate" about a language they'll be spending all day programming in.  Some people might even think it's a trick question: If they actually do come up with five things, they'll be disqualified for hating C# too much to program well in.  Unfortunately, this kind of perverse trick question is not unheard of in interviews.

Instead, you could ask What would you improve about C# if it were up to you?  This allows the interviewee to answer with any number of things.  This phrasing also trades the negativity of the word "hate" for the relatively positive "improve."


答:
The unit/acceptance tests are stronger documentation on how the system works than any piece of paper could ever be.

However, document the design any way that works for you; XP does not tell you that you cannot 'think on paper' or generate supporting documentation as you see fit, it just does not require such things

Title: Extreme Programming - documenting implementation?

Body:
In extreme programming methodology, what artifacts/ can be used to document the implementation?

I have used an activity diagram to document the design steps for each activity. I have read that for XP, the implementation chapter is the code itself.

I am developing an android application which consists of the GUI and java coding.


答:
As a developer you will come across this situation all the time - I have a problem with two solutions. Both appear to solve the problem, both are of similar complexity, there is no obvious reason to choose one over the other (patterns, practices, personal preference, etc). Which should I do?

The problem with the question you have posed above is that there is not enough context to make an assessment. For example, are there any external business or functional requirement that may help. ie. must all duplicates be removed before data can be appended? If there is a yes to this, then the first solution is the correct one because the second fails the requirements. Alternatively it may be that changes should only be made to worksheets, when additional data is about to be added so that any failure will leave the maximum number of worksheets in their original condition. In this case, the second solution is the best and the first fails.

If there is no such requirements to be factored in then the answer is a purely personal preference. Mine would be the second option. There is no difference in terms of stability or speed between the solutions.


答:
Documentation is something that is as important as database design, UI's and any number of other things that I've heard developers deride. The trick that agile is trying to teach people is to learn what is necessary and what is cruft. In the past, a lot of documentation was cruft. That's why companies would spend millions of dollars generated specifications that were promptly thrown out by the developer teams. Overly detailed, and often as over engineered as the code that was generated from it. Lately some people have gone the other extreme and say thing like all code should be self documenting and "Just go read the code". Just as silly.

The code you are writing is there to solve a problem, so consider the documentation as also needing to solve a problem. Ask yourself - why do I need this documentation? and ... following agile practices ... whats the simplest solution that will solve the problem in the clearest way? But most importantly - who am I writing this for? and what level of understanding am I going to assume they have?

There is no hard and fast rules either in programming or writing documentation. Each must fit the problem and the context of the problem. Treat all the available options as a palette of solutions you can pick and choose from to apply to your project. Choose the best options as you see them, and don't be afraid to change that at a later date.


问:
How To Handle Login For An Unofficial API?
I am building a tool to access some data on a site (Fitocracy) and I would like to turn it into an unofficial partial API, as no official API exists.

If you are not logged in, you cannot get access to any data, so my tool uses Ruby's mechanize to log in (with my account) and scrape some data from a page.

How should I handle this when I turn it into an API?  I am worried that people won't feel comfortable sending their login credentials through an unofficial API and I don't want to just circumvent the login to the site by giving everybody access through a dummy account.

答:
I'm Kasra Rahjerdi, a Software Engineer at Fitocracy. Before I joined the team, I actually created a reverse engineered copy of the mobile site's API with the goal of creating my own Android app off of it, so I can relate to what you're asking.

To directly respond to your question: Even if an app is open-source, the average user is going to be confused and hesitant to hand over their data to a third party, unless the developer name for the application is the company's name. I assume you're asking this question in regards for creating an API to create an Android application, in which case I'd strongly recommend against doing this because publicly releasing an application and API based off of our information will lead to hassles for the both of us. Users finding your application will be contacting you asking you why X doesn't work where it works on the iPhone app, and users finding the product through you will be leaving our ecosystem after the initial impression because the #1 thing our iPhone app is based off of is the perfect UX that we want.

But, I can't stop you from doing anything, so here's a GitHub project of another reverse engineered version of our API with a barebones Android app that you can use as a stepping stone if you want: https://github.com/walialu/Unofficial-Fitocracy.com-Android-App I'll just tell you that the creation of that application created a lot of chaos for us, since we had confused users left and right.

And to go back to your direct question: In the day and age of oAuth I really believe that the average consumer is hesitant to give user information unless they're on the application website of the supplier of data, so I wouldn't ask the user for username/password.