答:
When I'm asked to start the development of B which is sharing 80% functionality with A, I will either:

Clone A and modify it.

Extract the functionality that both A and B share into C which they will use.

Make A configurable enough to fulfill the needs of both B and itself (therefore B is embedded in A).

You chose 1, and it doesn't seem to fit your situation well. Your mission is to predict which of 2 and 3 is a better fit.

Title: How do you organize highly customized software?

Body:
I'm working on a large software project which is highly customized for various customers arround the world. This means that we have maybe 80% code which is common between the various customers, but also a lot of code which has to change from one customer to the other. In the past we did our development in separate repositories (SVN) and when a new project started (we have few, but large customers) created another repository based on whatever past project has the best code basis for our needs. This has worked in the past, but we ran into several problems:

Bugs which are fixed in one repository are not patched in other repositories. This might be a problem of organization, but I find it difficult to fix and patch a bug in 5 different repositories, keeping in mind that the team maintaining this repository might be in another part of the world and we don't have their test environment, neither know their schedule or what requirements they have (a "bug" in one country might be a "feature" in another).

Features and improvements made for one project, which might also be useful for another project are lost or if they are used in another project often cause big headaches merging them from one code base to another (since both branches might have been developed independently for a year).

Refactorings and code improvements made in one development branch are either lost or cause more harm than good if you have to merge all these changes between the branches.

We are now discussing how to solve these problems and so far came up with the following ideas on how to solve this:

Keep development in separate branches but organizing better by having a central repository where general bug fixes are merged into and having all projects merge changes from this central repository into their own on a regular (e.g. daily) basis. This requires huge discipline and a lot of effort for merging between the branches. So I'm not convinced that it will work and we can keep this discipline, especially when time pressure puts in.

Abandon the separate development branches and have a central code repository where all our code lives and do our customization by having pluggable modules and configuration options. We are already using Dependency Injection containers to resolve dependencies in our code and we are following the MVVM pattern in most of our code to cleanly separate business logic from our UI.

The second approach seems to be more elegant, but we have many unsolved problems in this approach. For example: how do handle changes/additions in your model/database. We are using .NET with Entity Framework to have strongly typed entities. I don't see how we can handle properties which are required for one customer but useless for another customer without cluttering our data model. We are thinking of solving this in the database by using satellite tables (having a separate tables where our extra columns for a specifiy entity live with a 1:1 mapping to the original entity), but this is only the database. How do you handle this in code? Our data model lives in a central library which we would not be able to extend for each customer using this approach.

I'm sure that we are not the only team struggling with this problem and I'm shocked to find so little material on the topic.

So my questions are the following:

What experience do you have with highly customized software, what approach did you choose and how did it work for you?

What approach do you recommend and why? Is there a better approach?

Are there any good books or articles on the topic that you can recommend?

Do you have specific recommendations for our technical environment (.NET, Entity Framework, WPF, DI)?

Edit:

Thanks for all the suggestions. Most of the ideas match those that we already had in our team, but it is really helpful to see the experience you had with them and tips to better implement them.

I'm still not sure which way we will go and I'm not making the decision (alone), but I will pass this along in my team and I'm sure it will be helpful.

At the moment the tenor seems to be a single repository using various customer specific modules. I'm not sure our architecture is up to this or how much we have to invest to make it fit, so some things might live in separate repositories for a while, but I think it's the only longterm solution that will work.

So, thanks again for all responses!


问:
How do you organize highly customized software?
I'm working on a large software project which is highly customized for various customers arround the world. This means that we have maybe 80% code which is common between the various customers, but also a lot of code which has to change from one customer to the other. In the past we did our development in separate repositories (SVN) and when a new project started (we have few, but large customers) created another repository based on whatever past project has the best code basis for our needs. This has worked in the past, but we ran into several problems:

Bugs which are fixed in one repository are not patched in other repositories. This might be a problem of organization, but I find it difficult to fix and patch a bug in 5 different repositories, keeping in mind that the team maintaining this repository might be in another part of the world and we don't have their test environment, neither know their schedule or what requirements they have (a "bug" in one country might be a "feature" in another).

Features and improvements made for one project, which might also be useful for another project are lost or if they are used in another project often cause big headaches merging them from one code base to another (since both branches might have been developed independently for a year).

Refactorings and code improvements made in one development branch are either lost or cause more harm than good if you have to merge all these changes between the branches.

We are now discussing how to solve these problems and so far came up with the following ideas on how to solve this:

Keep development in separate branches but organizing better by having a central repository where general bug fixes are merged into and having all projects merge changes from this central repository into their own on a regular (e.g. daily) basis. This requires huge discipline and a lot of effort for merging between the branches. So I'm not convinced that it will work and we can keep this discipline, especially when time pressure puts in.

Abandon the separate development branches and have a central code repository where all our code lives and do our customization by having pluggable modules and configuration options. We are already using Dependency Injection containers to resolve dependencies in our code and we are following the MVVM pattern in most of our code to cleanly separate business logic from our UI.

The second approach seems to be more elegant, but we have many unsolved problems in this approach. For example: how do handle changes/additions in your model/database. We are using .NET with Entity Framework to have strongly typed entities. I don't see how we can handle properties which are required for one customer but useless for another customer without cluttering our data model. We are thinking of solving this in the database by using satellite tables (having a separate tables where our extra columns for a specifiy entity live with a 1:1 mapping to the original entity), but this is only the database. How do you handle this in code? Our data model lives in a central library which we would not be able to extend for each customer using this approach.

I'm sure that we are not the only team struggling with this problem and I'm shocked to find so little material on the topic.

So my questions are the following:

What experience do you have with highly customized software, what approach did you choose and how did it work for you?

What approach do you recommend and why? Is there a better approach?

Are there any good books or articles on the topic that you can recommend?

Do you have specific recommendations for our technical environment (.NET, Entity Framework, WPF, DI)?

Edit:

Thanks for all the suggestions. Most of the ideas match those that we already had in our team, but it is really helpful to see the experience you had with them and tips to better implement them.

I'm still not sure which way we will go and I'm not making the decision (alone), but I will pass this along in my team and I'm sure it will be helpful.

At the moment the tenor seems to be a single repository using various customer specific modules. I'm not sure our architecture is up to this or how much we have to invest to make it fit, so some things might live in separate repositories for a while, but I think it's the only longterm solution that will work.

So, thanks again for all responses!

答:
I worked for many years on a Pension Administration application which had similar issues.  Pension plans are vastly different between companies, and require highly specialized knowledge for implementing calculation logic and reports and also very different data design.  I can only give a brief description of part of the architecture, but maybe it will give enough of the idea.

We had 2 separate teams: a core development team, which was responsible for the core system code (which would be your 80% shared code above), and an implementation team, which had domain expertise in pension systems, and was responsible for learning client requirements and coding scripts and reports for the client.

We had all of our tables defined by Xml (this before the time when entity frameworks were time-tested and common).  The implementation team would design all the tables in Xml, and the core application could be prompted to generate all the tables in Xml. There were also associated VB script files, Crystal Reports, Word docs etc. for each client.  (There was also an inheritance model built into the Xml to enable reusing other implementations).

The core application (one application for all clients), would cache all the client specific stuff when a request for that client came, and it generated a common data object (kind of like a remote ADO record set), which could be serialized and passed around.

This data model is less slick that entity/domain objects, but it is highly flexible, universal, and can be processed by one set of core code.  Perhaps in your case, you could define your base entity objects with only the common fields, and have an additional Dictionary for custom fields (add some kind of set of data descriptors to your entity object so that it has meta data for the custom fields.)

We had separate source repositories for the core system code and for the implementation code.

Our core system actually had very little business logic, other than some very standard common calculation modules.  The core system functioned as: screen generator, script runner, report generator, data access and transport layer.

Segmenting core logic and customized logic is a tough challenge. However, we always felt it was better to have one core system running multiple clients, rather than multiple copies of the system running for each client.

ContentLicense: CC BY-SA 3.0


答:
One of the projects I've worked on supported multiple platforms (more than 5) across a large number of product releases.  A lot of the challenges you are describing were things we faced, albeit in a slightly different way.  We had a proprietary DB, so we didn't have the same types of problems in that arena.

Our structure was similar to yours, but we had a single repository for our code.  Platform specific code went into their own project folders within the code tree.  Common code lived within the tree based upon what layer it belonged to.

We had conditional compilation, based upon the platform being built.  Maintaining that was kind of a pain, but it only had to be done when new modules were added at the platform specific layer.

Having all of the code in a single repository made it easy for us to make bug fixes across multiple platforms and releases at the same time.  We had an automated build environment for all the platforms to serve as a backstop in case new code broke a presumed unrelated platform.

We tried to discourage it, but there would be cases where a platform needed a fix based upon a platform-specific bug that was in otherwise common code.  If we could conditionally override the compile without making the module look fugly, we'd do that first.  If not, we would move the module out of common territory and push it into platform specific.

For the database, we had a few tables that had platform specific columns / modifications.  We would make sure that every platform version of the table met a baseline level of functionality so common code could reference it without worrying about platform dependencies.  Platform specific queries / manipulations were pushed into the platform project layers.

So, to answer your questions:

Lots, and that was one of the best teams I've worked with.  Codebase at that time was around 1M loc.  I didn't get to choose the approach, but it worked out pretty dang well.  Even in hindsight, I haven't seen a better way of handling things.

I recommend the second approach you suggested with the nuances I mention in my answer.

No books that I can think of, but I would research multi-platform development as a starter.

Institute some strong governance.  It's the key to making sure your coding standards are followed.  Following those standards is the only way to keep things manageable and maintainable.  We had our share of impassioned pleas to break the model we were following, but none of those appeals ever swayed the entire senior development team.


问:
Unit Tests code duplication?
How can I avoid code duplication in unit tests?

Using Java and JUnit suppose I have something like this:

```<code>public interface Arithmetic<T> {
    public T add(T a, T b);
    public T sub(T a, T b);
}

public void IntegerArithmetic<Integer> {
    //
}

public void DoubleArithmetic<Double> {
    //
}
</code>```

And the test class:

```<code>public class TestArith {

private Arithmetic<Integer> arith;

@Before
public void init() {
    Arithmetic<Integer> arith = new IntegerArithmetic();
    Integer term1 = 4;
    Integer term2 = 3;
}

@Test
public void testAdd() {
     assertEquals(7, arith.add(term1, term2));
}

@Test
public void testAdd() {
     assertEquals(1, arith.sub(term1, term2));
}
}
</code>```

The problem is that the test class for the DoubleArithmetic class should look exactly the same; the only difference is in @Before init() where the initialization of the concrete type is done. How can this code duplication be avoided?

答:
This is not always so.

Obviously, tests for 10 / 4 or 1 << 31 * 5 will give different results in IntegerArithmetic and DoubleArithmetic.

If there's a large subset where IntegerArithmetic and DoubleArithmetic should act the same, try instantiating a class based on a common interface, e.g. Arithmetic<java.lang.Number>.

Let me elaborate a bit.

There are two places where code duplication may arise: the initialization, which only differs by the class being tested, and the test cases.

Common tests can go into a common case which can be subclassed, and each subclass's .setUp() will instantiate its own concrete instance of Arithmetic to test.

Class-specific tests get their own test cases.

Initialization code can be de-duplicated by using a parametrized base class from which concrete instances of TestCase will arise, as @Skillwired proposes.

Title: Unit Tests code duplication?


答:
I've worked on a smaller system (20 kloc), and found that DI and configuration are both great ways to manage differences between clients, but not enough to avoid forking the system. The database is split between an application specific part, which has a fixed schema, and the client dependent part, which is defined through a custom XML configuration document.

We've kept a single branch in mercurial that's configured as if it was deliverable, but branded and configured for a fictional client. Bug fixes are mainlined into that project, and new development of core functionality only happens there. Releases to actual clients are branches off of that, stored in their own repositories. We keep track of large changes to the code through manually written version numbers and track bug fixes using commit numbers.


问:
Mixing languages in .Net
I know that .Net provides the feature to mix several languages within the same application (there are some constraints of course, but this is not essential). Theoretically, this might be done because the languages supported by .Net do not fully expose all the features it can provide. IL does of course. So when you need a feature that the current language doesn't provide, you could write it in another .Net language. The whole code would be translated into IL, and so you would gain more features.

From my personal experience, I was writing a project in C# and needed to integrate a small project written in C++ under .Net. When I consulted with some more experienced programmers, they said that it would be much easier to "translate" the C++ code into C# than integrate it. Since I had little time, it was what I did, and it was quite easy (the project was quite small).

So my question is, has anyone experienced a real-life situation when mixing languages is an absolute necessity?

答:
I did work on a project where we had a UI written in VB.NET, and calculations written in C#.  This was primarily due to the UI developer not having experience in C#, and the calculation developer having no experience in VB.NET. With .NET, everything just worked together.

Ideally, the developers should have agreed on the language, but it did work for a rapid project completion time (no language ramp up).

Title: Mixing languages in .Net


问:
Should a github maintainer rewrite author's in pull requests?
I'm not a programmer by profession, but I do some coding and have used github some.  I've run across what I find to be a surprising situation.  I'm very familiar with git.

There is a project which I found a (small) bug in that was affecting me.  I spent an afternoon finding and fixing it.  I forked the repository, commit the change, and issued a pull request.   After seeing that it was closed as "Merged into development branch" I figured all was well.

I was browsing the repo today getting ready to remove my branch, and I can't find where the commit was merged into the maintainer's repo at all.  After some time I realize it's been added as a commit, but the author is no longer me.

As far as I can tell the only way to do that would be to specifically use a rebase, amend, or other history rewrite to remove the original author.

This seems very wrong to me.  At best it's confusing, at worst the author of this repo is taking credit for everyone's commits and then the history of the original contributor is lost.  Again it's a small bug, I don't use this for my professional resume, it just seems dishonest.

Is this normal?
Should I say something about it?

Edit: The general feeling seems to be that I should go ask, so I'll do just that this morning.

As per the request below.  I've checked and my code exists and was applied exactaly as I wrote it (including the comment).  I verified that both the committer and author have been changed.  There was one additional change also added at the same time as my changes.  It's a single line, which would affect the patch as well as other code before it.  IE the one line addition is not related to the bug I was fixing.

Update
It seems the answer was that the author maintains a development branch and does not want to merge from his master branch into it.  He re-authored my commit to avoid a merge.  I wasn't concerned with the original branch b/c git's plenty powerful to cherry-pick, rebase, and merge commits around as needed.

Is this typical on github?

Should I be contacting the maintainer of a project to ask which branch to apply patches to?

答:
To answer your updated question:

It is hard to say what is typical on github, beyond saying that typically every project is different and each has their own preferred workflow. Generally the best approach before sending a pull request is to ask what their workflow is or try to see if you can tell based off previous closed pull requests.

My personal experience has been if you do not ask, generally they will at best close the pull request without comment (worse case), or best case they leave a comment explaining what the procedure asking you to update your pull request. I will say it does seem odd the way the maintainer in your case handled it, but it may have just been the path of least resistance for them. I doubt it was intentionally meant to steal credit though.

I would suggest you ask the maintainer to add documentation explaining how they would like to receive pull requests and against what branch to avoid the confusion and lack of credit in the future. I wish more projects provided this documentation, as I think it would make people more inclined to participate in the project.


答:
Declare class TestArith as abstract. Then create two classes, TestIntegerArith and TestDoubleArith extending TestArith. In the TestArith create an abstract method getArithmetic, which returns an instance of Arithmetic. Then change the tests to get Arithmetic instance by calling getArithmetic.

So it would look like this:

```<code>public abstract class TestArith<T> {
  protected abstract Arithmetic<T> getArithmetic();

  @Test
  public void testAdd() {
      assertEquals(7, getArithmetic().add(term1, term2));
  }
}
</code>```

Title: Unit Tests code duplication?

Body:
How can I avoid code duplication in unit tests?

Using Java and JUnit suppose I have something like this:

```<code>public interface Arithmetic<T> {
    public T add(T a, T b);
    public T sub(T a, T b);
}

public void IntegerArithmetic<Integer> {
    //
}

public void DoubleArithmetic<Double> {
    //
}
</code>```

And the test class:

```<code>public class TestArith {

private Arithmetic<Integer> arith;

@Before
public void init() {
    Arithmetic<Integer> arith = new IntegerArithmetic();
    Integer term1 = 4;
    Integer term2 = 3;
}

@Test
public void testAdd() {
     assertEquals(7, arith.add(term1, term2));
}

@Test
public void testAdd() {
     assertEquals(1, arith.sub(term1, term2));
}
}
</code>```

The problem is that the test class for the DoubleArithmetic class should look exactly the same; the only difference is in @Before init() where the initialization of the concrete type is done. How can this code duplication be avoided?

Body:
Declare class TestArith as abstract. Then create two classes, TestIntegerArith and TestDoubleArith extending TestArith. In the TestArith create an abstract method getArithmetic, which returns an instance of Arithmetic. Then change the tests to get Arithmetic instance by calling getArithmetic.

So it would look like this:

public abstract class TestArith<T> {
  protected abstract Arithmetic<T> getArithmetic();

  @Test
  public void testAdd() {
      assertEquals(7, getArithmetic().add(term1, term2));
  }
}


问:
Why is OOP difficult?
When I started using an object-oriented language (Java), I pretty much just went "Cool" and started coding. I've never really thought about it until only recently after having read lots of questions about OOP. The general impression I get is that people struggle with it. Since I haven't thought of it as hard, and I wouldn't say I'm any genius, I'm thinking that I must have missed something or misunderstood it.

Why is OOP difficult to understand? Is it difficult to understand?

答: You should read Objects Never? Well, Hardly Ever. (ACM membership required) by Mordechai Ben-Ari who suggests that OOP is so difficult, because it's not a paradigm that's actually natural for modeling anything. (Though I have reservations about the article, because it's not clear what criteria he feels a program needs to satisfy to say that it's written on the OOP paradigm as opposed to a procedural paradigm using an OO language.)</p>

ContentLicense: CC BY-SA 2.5

Title: Why is OOP difficult?


问:
Should I use events in this case?
I'm creating a video player, like a custom YouTube player.

All of the GUI elements (progress bar, video player, play button, ...) are different classes, but I obviously need them to communicate. When the progress bar is clicked, or the slider is moved, it needs to send a "seek(x)" command to the video player. Similarly, the video player needs to update the progressbar every frame.

Currently I'm doing this by having almost all elements have a link to each other.
So when I create the progress bar, I'm telling it where the video player is.

But after a while this becomes more and more complicated, and I'm wondering if events would be a better way to do this. Or a main controller class that has all the connections.
What should I do?

答:
Ideally, your GUI classes should have no idea they are even part of a video player.  They interact with the user and that's it.  This is called the Single Responsibility Principle.

In your case, I would create a TimeBase class to keep track of what frame is currently playing.  It would have seek() and nextFrame() methods to change the current frame.  Objects would call addSubscriber(subscriber, interval) to receive events when the current frame changes.  The interval parameter is for widgets that don't need a one-frame resolution, like a display that changes every second, for example.

The next layer down would be adapter classes for every widget type, which implement both the TimeBaseListener interface and the click/slide/whatever listener interfaces from the GUI class, and translate between them.  For example, a ProgressBarAdapter would get pointers to both the TimeBase and ProgressBar objects during construction.  It would listen for slider moved events, translate the new slider value into a frame number, and call timeBase.seek().  When it received a FrameChanged event, it would translate the frame number into the progress bar value and change the GUI accordingly.

A lot of people balk at the second layer, preferring to roll that functionality into a class derived from the widget class.  A lot of tutorials on languages' official websites even use that method, but they shouldn't.  It violates both the single responsibility principle and preferring composition over inheritance.

In less buzz-wordy terms, the problem with inheriting from the widget class is now you are locked into its inheritance hierarchy, and can never choose one more suitable to your application.  You also can't split the class when it gets too big.  What works okay on small website tutorials illustrating one small concept will not scale well into a real life application.

Title: Should I use events in this case?


问:
std::shared_ptr as a last resort?
I was just watching the "Going Native 2012" streams and I noticed the discussion about std::shared_ptr. I was a bit surprised to hear Bjarne's somewhat negative view on std::shared_ptr and his comment that it should be used as a "last resort" when an object's life-time is uncertain (which I believe, according to him, should infrequently be the case).

Would anyone care to explain this in a bit more depth? How can we program without std::shared_ptr and still manage object life-times in a safe way?

答:
I'll answer from my experience with Objective-C, a language where all objects are reference counted and allocated on the heap. Because of having one way to treat objects, things are a lot easier for the programmer. That has allowed for standard rules to be defined that, when adhered, guarantee code robustness and no memory leaks. It also made possible for clever compiler optimizations to emerge like the recent ARC (automatic reference counting).

My point is that shared_ptr should be your first option rather than the last resort. Use reference counting by default and other options only if you are sure of what you are doing. You will be more productive and your code will be more robust.

OwnerDisplayName: ronag

Title: std::shared_ptr as a last resort?


问:
BDD in .NET - Chicken or Egg or..?
Predicate: I'm brand new to BDD / TDD, but I've done my homework.

I'm trying to put everything I've read / learned into practice with VS2010, SpecFlow and NUnit. Things are working, but it's quickly becoming a chicken / egg scenario within a blur of unit and acceptance tests. I hope solving these BASIC questions will make everything click.

From my reading, I expected to:

Write a Feature

Define Acceptance Tests that fail

Define Unit Tests that fail

Make Unit Tests pass

Now the Acceptance Test pass

Write the next Feature

That all makes perfect sense, I'm just having a hard time seeing what's what in code...

In practice:

Write a Feature with Scenarios - fine.

Generating Step Definitions - fine.

Ahhh.

Does completing the step definitions (providing context in GIVEN, setting things up in WHEN and making assertions in THEN) constitute a completed acceptance test? Do you write out classes and methods here first as if you'd defined them already, and generate skeleton code via the IDE? Presumably the assertion needs some kind of implementation to work, but then the implementation code won't have been unit tested? Ahhh.

I've looked at a number of example projects and codebases, but as they're all complete there's little sense of ordering in terms of the development process.

Any clarification of steps, examples, etc. would be great!

答:
Your order is wrong, methinks:

Define Acceptance Tests that fail

Define Unit Tests that fail

Make Unit Tests pass by writing the logic required for the feature

Make the Acceptance Test pass by integrating the logic into the existing system

Repeat with the next defined requirement

Basically, in both TDD and BDD, you always define what your new code should do before you write a line of that code. So, breaking it down, the real process is:

Read the requirements for the next story, and break it down into individual pieces that can be defined in SpecFlow as assertions using "Given", "When" and "Then" clauses.

Write the first assertion into SpecFlow. This is your "acceptance test" and it will fail because the behavior is not in the system.

"Drill down": Identify the code object that is most directly interacted with from outside the system's boundaries, which must exhibit the newly-defined behavior. That object does not necessarily exist in the current codebase. Write a test that asserts the object exhibits the desired behavior. Repeat; find the object(s) that the one you just tested must interact with to exhibit the defined behavior. Define tests that assert these objects do what they need to. Repeat until you identify one or more lines of actual code within a method which do not yet exist or which must change in order to begin exhibiting the behavior. Along the way, tests that must touch another object, the network, file system, DB, etc to have value are "integration tests"; tests that can operate within the boundary of a single class, or that have value given "test data" in the form of mocked objects, are "unit tests".

Now, the coding of the actual feature begins. Do what you have to to make the tests you wrote, and all other tests in the system, pass; unit first, then integration, then acceptance. It is not unheard of to write a code that passes first try; that indicates either a bad thing (you didn't make the correct assertions; go back to step 3) or good (the behavior you need already exists; move on). It's also not unheard of to make a change that passes a new test but fails an old one; either you made an incorrect change, or the assertions of the old test are now incorrect in light of the new requirement. It's your job to determine which.

Once everything is "green", refactor the code you wrote to pass the tests; organize it, merge code blocks that do the same thing, adhere to good coding patterns. Make sure all the tests still pass, of course.

Repeat from step 2 with the next assertion of the story requirements.

Repeat with the next story.

Along the way, it's perfectly normal to have to define a new object or object member that never existed before, but which must now exist and function correctly. Here's where TDD starts paying you back, and where refactoring assistance like ReSharper pay for themselves several times over; simply code the test as if the code object you need already existed. This code obviously won't compile; that's your first goal, and ReSharper can fix pretty much all the red you'll see with a few presses of Alt+Enter. Once it compiles, the test still fails because the skeleton exists, but the logic still doesn't. Code that logic until the test passes, and then move on.

OwnerDisplayName: Tom Tom

Title: BDD in .NET - Chicken or Egg or..?


答:
I personally found the mechanics of OOP fairly easy to grasp.  The hard part for me was the "why" of it.  When I was first exposed to it, it seemed like a solution in search of a problem.  Here are a few reasons why I think most people find it hard:

IMHO teaching OO from the beginning is a terrible idea.  Procedural coding is not a "bad habit" and is the right tool for some jobs.  Individual methods in an OO program tend to be pretty procedural looking anyhow.  Furthermore, before learning procedural programming well enough for its limitations to become visible, OO doesn't seem very useful to the student.

Before you can really grasp OO, you need to know the basics of data structures and late binding/higher order functions.  It's hard to grok polymorphism (which is basically passing around a pointer to data and a bunch of functions that operate on the data) if you don't even understand the concepts of structuring data instead of just using primitives and passing around higher order functions/pointers to functions.

Design patterns should be taught as something fundamental to OO, not something more advanced.  Design patterns help you to see the forest through the trees and give relatively concrete examples of where OO can simplify real problems, and you're going to want to learn them eventually anyhow.  Furthermore, once you really get OO, most design patterns become obvious in hindsight.

Title: Why is OOP difficult?

Body:
When I started using an object-oriented language (Java), I pretty much just went "Cool" and started coding. I've never really thought about it until only recently after having read lots of questions about OOP. The general impression I get is that people struggle with it. Since I haven't thought of it as hard, and I wouldn't say I'm any genius, I'm thinking that I must have missed something or misunderstood it.

Why is OOP difficult to understand? Is it difficult to understand?


答:
Talk through the scenarios in conversation with your business expert or proxy.

Question the scenarios. Find more scenarios.

Write the scenarios down. Honestly, it doesn't have to be in SpecFlow to start with.

If it's a new UI, it's probably going to be wrong the first time, so if you start writing automated scenarios here you may find yourself thrashing horribly with them. Don't write automated scenarios for new UIs. Wait till it's stabilized. Get something small working - it can have hard-coded data if you like. Unit testing is fine here. Remember to get feedback from your business expert.

Now that the UI has stabilized, you can automate the scenarios.

Now the UI has stabilized, add another scenario that captures the next piece of behavior and make it work.

That's pretty much how my cycle goes. It's perfectly OK not to write automated tests for a brand new UI, and to write them afterwards.

Just make sure that either your business have clearly articulated what they want, or you're both aware that they're uncertain and you've worked out a mechanism for giving them something to try out so they can provide feedback. In that second situation you might not be able to come up with particularly coherent scenarios anyway.

Title: BDD in .NET - Chicken or Egg or..?

Body:
Predicate: I'm brand new to BDD / TDD, but I've done my homework.

I'm trying to put everything I've read / learned into practice with VS2010, SpecFlow and NUnit. Things are working, but it's quickly becoming a chicken / egg scenario within a blur of unit and acceptance tests. I hope solving these BASIC questions will make everything click.

From my reading, I expected to:

Write a Feature

Define Acceptance Tests that fail

Define Unit Tests that fail

Make Unit Tests pass

Now the Acceptance Test pass

Write the next Feature

That all makes perfect sense, I'm just having a hard time seeing what's what in code...

In practice:

Write a Feature with Scenarios - fine.

Generating Step Definitions - fine.

Ahhh.

Does completing the step definitions (providing context in GIVEN, setting things up in WHEN and making assertions in THEN) constitute a completed acceptance test? Do you write out classes and methods here first as if you'd defined them already, and generate skeleton code via the IDE? Presumably the assertion needs some kind of implementation to work, but then the implementation code won't have been unit tested? Ahhh.

I've looked at a number of example projects and codebases, but as they're all complete there's little sense of ordering in terms of the development process.

Any clarification of steps, examples, etc. would be great!


答:
Generally, when doing BDD you dive in and out of a TDD stance. Your acceptance test defines the feature scope. Within the step definition, you should be 'driving' your scenarios. This is closer to what the user does, so maybe you use a GUI driver like Selenium. At this level you're thinking in terms of your story role (as a...) and the actions available in the defined step context. Maybe this is a very high-level api, maybe it is the cross-functional flow of a process. The main attribute is that this is at the level of value to the role and should look like a user/consumer taking action.

When you define the high-level surface of your implementation, you then dive into TDD mode. Commit a TDD iteration, then surface back to BDD mode.

Imagine a scenario for a website:

Given a Visitor

And the Visitor is on the Registration View

And the Visitor has provided all the required inputs

When the Visitor Registers

Then a Registered User is created

And the Registered User matches the Visitor input

And a Confirmation Email is sent to the Visitor provided email address

So, the step definitions all need to be filled in somehow. This is the BDD implementation mode.

Given a Visitor? Ok, what does it mean to visit the site? HTTP Request? How do I know? Cookies?

On the Registration View? Should I use Watin to drive this process. Are there URI end-points? How do I drive my application?

Required Inputs? How do I programmatically provide my system with user input? HTML Form?

Visitor Registers? How is this action triggered? Is this an HTTP Post? At this point, you're seeing the top-level transaction-script-like view of your system.

At each point, you may flesh out your design using TDD.

Given a Visitor? Ok, new design choices. Is a Visitor a type in my system? Or do I call them a User with Registered=false? Use TDD to drive the design of a Visitor. Think about handling authentication in this level.

Visitor Registers? Is this a service? I want to say something like Register(visitor) in my test and drive it out using TDD.

Email is sent? Again, there's a low-level and a high-level design to flesh out.

In sum, BDD scenarios (collections of Step Definitions) are statements about the worlds. Preconditions, Action, Postconditions (just like Arrange, Act, Assert) that are important to the user of the system. TDD is important to the programmer/designer of the system. But you use both when practicing BDD.

Title: BDD in .NET - Chicken or Egg or..?


问:
When you won't need a language anymore, should you still use it?
My first main language was Java.  However, over the years I've dropped Java in favor for Python, JavaScript, bash, etc.  I still have advanced reading knowledge of Java, but since I haven't coded in it for so long, my writing knowledge is intermediate at most.  The other day, while looking at some old code written in Java, I got inspiration to re-write it as a learning experience to reacquaint myself.

It was at that point that I stopped to think that if I wrote this in Java, it would be nice, but when the renewed inspiration had hit me, I wanted to implement it as a web app (it was a game), so other people could play it.

So now here's the dilemma: Do I re-write (and heavily refactor) the code I've previously written in Java, and then in JavaScript (for the web version), or do I just forget about Java altogether and re-write it in JavaScript?

EDIT: I have no problem writing in Java first and then JavaScript, but I'm more likely than not going to need Java anymore for a long while.  What I'm trying to ask is whether or not I should rewrite the old code in Java first, to practice a skill I may not need in the future.  The actual languages are less important than that question.

答:
Consider your end result - an online game, written in JavaScript.

As such, by all means, take inspiration from your old codebase and plan ahead.

The way I would approach this would be to figure out what refactoring I would do and use both the old codebase and the refactoring plan as a blueprint for a new codebase using JavaScript.

My point is that if you are going to refactor to Java, then directly port to JavaScript, you will hit problems when porting from Java to JavaScript (idioms, how the different environmentw work, assumptions not relevant to Java etc...). Ditching the intermediary step you know that the JavaScript will not be a direct port and will be already ahead in regards to issues with a direct port.

Since this is a personal project designed for your enjoyment, you should aim for that - you don't have to refactor the whole codebase. If you start and feel that it is not constructive to your goals (rekindling the fun in programming), stop and go ahead with the re-write in JavaScript, without having done a whole lot of work that you find tedious.


问:
What's the benefit of a singleton over a class in objective-c?
They both seem to take about the same amount of effort to use:

Singleton: needs a .h and .m file, has to be imported into any class you want to call it from and then has to be instantiated

How is that any different than a class?

答: A singleton is a class and behaves exactly like any other class, the only exception being that any instances of a singleton reference the same object data. This means that any instance of a singleton class are actually all the same instance.


问:
hash with file instead of array
Is it possible to use hash function but with File instead of Array, and it's gonna be saving the record in a file position and then search will fseek to that position, but I'm not sure how to open a file with let's say 1000 line, do you think that method could work?</p>

答:
Sure, if you have a hashing function that can neatly map your data.  Two things to keep an eye on:

Does your OS/file system support sparse files?  Can you seek beyond the end of the file and write a new record without intervening data?

How are you going to handle hash collisions?  Will each record have some kind of header that contains a pointer to the next bucket in an overflow chain, or will you just overflow into the next available slot?  If you just go to the next slot, how will you tell if it's available?

I'd recommend reading up on ISAM files, they're pretty close to what you're looking to do.

Title: hash with file instead of array


问:
Automatic programming: write code that writes code
After reading the book The Pragmatic Programmer, one of the arguments I found most interesting was "write code that writes code".

I tried searching over the net for some more explanations or articles about it, and while I found some good articles on the subject, I still haven't found any specific code implementation or good examples.

I feel it's still not a so common argument, something that lacks documentation or it's not embraced by so many people, and I would like to know more about it.

What do you think about the subject? Is it something that will really increase your productivity? What are some good resources on the subject, among books, blogs, slideshows, etc?

Some code examples would be greatly appreciated to allow me to better understand its implementation.

Here's the wiki page on the subject with various relevant programming techniques, like Meta Programming, Generative Programming and Code Generation.

答:
You ask for examples....

When working with SQL, you shouldn't be changing the database directly, but instead are supposed to be executing scripts that make whatever changes you want, including structural changes to the database (adding tables, columns, primary keys, constraints and so forth).  Quite frequently you will need to do take the same action against a lot of tables or columns at the same time, and doing them one by one would be tedious, a short script that outputs a larger script that does what you want can be a real time saver.

For instance, before the DATE data-type was introduced to MS SQl Server, the only choice for a date column was DATETIME which has a time part -- a time part that makes dealing with the data a bit harder.  Upon upgrading to a version with the Date data-type, you might want to update the columns where the time is always 00:00.  In a database with dozens or even hundreds of DateTime columns this would be quite time consuming.  But it's easy to write a script that queries all of the tables, checking every column with a data type of DATETIME to see if it the time is ever anything but 00:00 and if not create an ALTER statement for the table/column to change the data type to DATE.  Presto, code that writes code.


问:
Is it bad to use Unicode characters in variable names?
I recently tried to implement a ranking algorithm, AllegSkill, to Python 3.

Here's what the maths looks like:

No, really.

This is then what I wrote:

```<code>t = (µw-µl)/c  # those are used in
e = ε/c        # multiple places.
σw_new = (σw**2 * (1 - (σw**2)/(c**2)*Wwin(t, e)) + γ**2)**.5
</code>```

I actually thought it is unfortunate of Python 3 to not accept √ or ² as variable names.

```<code>>>> √ = lambda x: x**.5
  File "<stdin>", line 1
    √ = lambda x: x**.5
      ^
SyntaxError: invalid character in identifier
</code>```

Am I out of my mind? Should I have resorted for a ASCII only version? Why? Wouldn't an ASCII only version of the above be harder to validate for equivalence with the formulas?

Mind you, I understand some Unicode glyphs look very much like each other and some like     ▄ (or is that ▗▖ ) or ╦  just can't make any sense in written code. However, this is hardly the case for Maths or arrow glyphs.

Per request, the ASCII only version would be something along the lines of:

```<code>winner_sigma_new = ( winner_sigma ** 2 *
                    ( 1 -
                     ( winner_sigma ** 2 -
                       general_uncertainty ** 2
                     ) * Wwin(t,e)
                    ) + dynamics ** 2
                   )**.5
</code>```

...per each step of the algorithm.

答: You didn't say what language/compiler you are using, but usually the rule for variable names is that they must start with an alphabetic character or underscore, and contain only alphanumerics and underscores.  A Unicode √ would not be considered alphanumeric, since it is a mathematical symbol instead of a letter.  However σ might be (since it is in the Greek alphabet) and á would probably be considered alphanumeric.</p>


问:
Why is the use of abstractions (such as LINQ) so taboo?
I am an independent contractor and, as such, I interview 3-4 times a year for new gigs.  I am in the midst of that cycle now and got turned down for an opportunity even though I felt like the interview went well.  The same thing has happened to me a couple of times this year.

Now, I am not a perfect guy and I don't expect to be a good fit for every organization.  That said, my batting average is lower than usual so I politely asked my last interviewer for some constructive feedback, and he delivered!

The main thing, according to the interviewer, was that I seemed to lean too much towards the use of abstractions (such as LINQ) rather than towards lower-level, organically grown algorithms.

On the surface, this makes sense--in fact, it made the other rejections make sense too because I blabbed about LINQ in those interviews as well and it didn't seem that the interviewers knew much about LINQ (even though they were .NET guys).

So now I am left with this question: If we are supposed to be "standing on the shoulders of giants" and using abstractions that are available to us (like LINQ), then why do some folks consider it so taboo?  Doesn't it make sense to pull code "off the shelf" if it accomplishes the same goals without extra cost?

It would seem to me that LINQ, even if it is an abstraction, is simply an abstraction of all the same algorithms one would write to accomplish exactly the same end.  Only a performance test could tell you if your custom approach was better, but if something like LINQ met the requirements, why bother writing your own classes in the first place?

I don't mean to focus on LINQ here.  I am sure that the JAVA world has something comparable, I just would like to know why some folks get so uncomfortable with the idea of using an abstraction that they themselves did not write.

UPDATE

As Euphoric pointed out, there isn't anything comparable to LINQ in the Java world.  So, if you are developing on the .NET stack, why not always try and make use of it?  Is it possible that people just don't fully understand what it does?

答:
I don't think it's the use of abstractions per se that's objectionable.  There are two other possible explanations.  One is that abstractions are all leaky at one time or another.  If you give the impression, correct or not, that you don't understand the underlying fundamentals, that might reflect poorly in an interview.

The other possible explanation is the fanboy effect.  If you talk excitedly about LINQ, and repeatedly bring it up in an interview with a company who doesn't use it and has no current plans to do so, that gives the impression that you would be dissatisfied or even disgruntled working with older technologies.  It can also give the impression that your enthusiasm for one product has blinded you to alternatives.

If you truly think you would be happy in a non-LINQ shop, try asking about what they do use, and tailor your answers accordingly.  Show them that while you prefer LINQ, you are competent using whatever tools are at hand.


答:
I think you are drawing a false conclusion, because your set of samples is too limited. Although I have seen a fair share of IT shops with strong aversion to anything "not invented there"1, none of them would disqualify candidates based on their preferences in the technology stack: they were rightfully convinced that they could teach the right candidate to use their home-grown libraries.

I seriously doubt that the company banned the use of LINQ outright. More likely, they wanted you to show them your skills at a deeper level.

For example, one way to figure out if you know your hash tables is to ask you to implement a primitive one on a whiteboard. This simple exercise reveals a surprising amount of data about your knowledge to the reviewer: he instantly learns if you know about hash code / equals, and what you know about hash collisions. At the same time, it is hard to imagine someone in their right mind re-implementing a hash table, because Microsoft did so good of a job at it. Same goes for many algorithms, such as sorting and searching: interviewers often would like to know if your background is enough to understand low-level interactions, rather than checking that you have a working knowledge of .NET libraries.

It is a near certainty that they would insist on you using library implementations rather than your own once you are hired to work for their company. But during the interview they would push you toward the low level code to gain better understanding of your true abilities.

1 one shop went as far as building its own rather primitive build tool!

Title: Why is the use of abstractions (such as LINQ) so taboo?

Body:
I am an independent contractor and, as such, I interview 3-4 times a year for new gigs.  I am in the midst of that cycle now and got turned down for an opportunity even though I felt like the interview went well.  The same thing has happened to me a couple of times this year.

Now, I am not a perfect guy and I don't expect to be a good fit for every organization.  That said, my batting average is lower than usual so I politely asked my last interviewer for some constructive feedback, and he delivered!

The main thing, according to the interviewer, was that I seemed to lean too much towards the use of abstractions (such as LINQ) rather than towards lower-level, organically grown algorithms.

On the surface, this makes sense--in fact, it made the other rejections make sense too because I blabbed about LINQ in those interviews as well and it didn't seem that the interviewers knew much about LINQ (even though they were .NET guys).

So now I am left with this question: If we are supposed to be "standing on the shoulders of giants" and using abstractions that are available to us (like LINQ), then why do some folks consider it so taboo?  Doesn't it make sense to pull code "off the shelf" if it accomplishes the same goals without extra cost?

It would seem to me that LINQ, even if it is an abstraction, is simply an abstraction of all the same algorithms one would write to accomplish exactly the same end.  Only a performance test could tell you if your custom approach was better, but if something like LINQ met the requirements, why bother writing your own classes in the first place?

I don't mean to focus on LINQ here.  I am sure that the JAVA world has something comparable, I just would like to know why some folks get so uncomfortable with the idea of using an abstraction that they themselves did not write.

UPDATE

As Euphoric pointed out, there isn't anything comparable to LINQ in the Java world.  So, if you are developing on the .NET stack, why not always try and make use of it?  Is it possible that people just don't fully understand what it does?


问:
If your algorithm is correct, does it matter how long it took you to write it?
I recently found out that Facebook had a programming challenge that if completed correctly you automatically get a phone interview.

There is a sample challenge that asks you to write an algorithm that can solve a Tower of Hanoi type problem. Given a number of pegs and discs, an initial and final configuration; Your algorithm must determine the fewest steps possible to get to the final configuration and output the steps.

This sample challenge gives you a 45 minute time limit but allows you to still test your code to see if it passes once your time limit expires.

I did not know of any cute math solution that could solve it, and I didn't want to look for one since I think that would be cheating. So I tried to solve the challenge the best I could on my own.

I was able to make an algorithm that worked and passed. However, it took me over 4 hours to make, much longer than the 45 minute requirement. Since it took me so much longer than the allotted time, I have not attempted the actual challenge.

This got me wondering though, in reality does it really matter that it took me that long? I mean is this a sign that I will not be able to get a job at a place like this (not just Facebook, but Google, Fog Creek, etc.) and need to lower my aspirations, or does the fact that I actually passed on my first attempt even though it took too long be taken as good?

答:
It does matter, to a company that is looking for general developers with good cash flow, because faster means more work can get done.  However, in many other cases (I would argue in most cases, actually), it doesn't matter as much as your ability to solve problems, and your ability to solve them well.

I can think of five different types of problem solvers:

Those who...

...can solve problems quickly, with a clean and efficient solution.

...can solve problems quickly, but with a dirty and inefficient solution.

...can solve problems slowly, but end up with a clean and efficient solution.

...can solve problems slowly, but end up with a dirty and inefficient solution.

...cannot solve problems, either quickly, or slowly.

A Facebook-style test explicitly weeds out #3, #4, and #5 candidates because it has a time constraint, so we know that this test is for employers who have determined that they should only hire #1 or possibly #2 candidates (depending on further screening).

Some examples:

An employer like Facebook might only be looking for #1 programmers only, since they can afford huge salaries for super-star programmers.

An employer that has a high-volume of one-off sales (like some web design shops) might only want a #2 developer, who are cheaper than the equally effective #1 developers.

An employer that has a specialized problem domain (such as writing loan origination software), might accept a #3 developer over a #1 developer, since a dual-degree genius developer might be super-expensive, or they might be hard to find.

An employer that doesn't care or has limited budget for various reasons might be OK with a #4 developer.

#5 developers get hired by firms that don't know what they're looking for and fail to screen those applicants out.


答:
Some .NET programmers, particularly those coming from either a classic VB/ASP or a C++ background, don't like new stuff like LINQ, MVC and Entity Framework.

Based on what I've observed, the ex-VB'ers in this group are likely to still be using a data access layers and other code originally written 10+ years ago. They'll also use old buzzwords like "n-tier" and the like and not really understand anything at all about anything beyond .NET Framework 2.0 nor are they wanting to learn anything about it.

The C++'ers tend to be academically oriented programmers who love coding cool algorithms, even if it means re-inventing the wheel. They hate depending on anything they didn't hand code themselves. A few of these people also delight in making interviewees feel inferior, especially those with a less traditional background.

You're likely to run into organizations like this when you're interviewing. But, you'll also run into some who are using newer methods. Don't let a few bad interviews throw you off.


问:
Order of subject and modifiers in variable names
I'm looking for experiences regarding the ordering of the subject and modifiers in variable names.

A simple object Shape would have just a subject for the variable name, such as Area.

A slightly more complex case Sphere which has a wall will have an inner volume and an outer volume, which is where my question comes into play.

What's preferred between Modifier-Subject or Subject-Modifier?

As an example set:

```
class Containers_Modifier_Subject
{
  AreaAdjustmentFactor
  WallThickness
  Height
  Length
  Width
  AdjustedArea
  SurfaceAreaInner
  SurfaceAreaOuter
  LongWallArea
  ShortWallArea
  TopArea
  InnerVolume
  OuterVolume
}

class Containers_Subject_Modifier
{
  AreaAdjustmentFactor
  WallThickness
  Height
  Length
  Width
  AreaAdjusted
  AreaInnerSurface
  AreaOuterSurface
  AreaLongWall
  AreaShortWall
  AreaTop
  VolumeInner
  VolumeOuter
}
```

The trigger for my question comes from an object that is similar to the examples.  There were enough variables in the object that only a portion displays in the code ahead / lookup window from the IDE.  I want to make sure that any future developer is quickly led to the correct variable that they'll be looking for without having to scroll up and down through the lookup window.

In my case, I was looking for the total area, but the area factor and adjusted area values had popped up first.

Consistency in naming as a code standard is a given.

Which naming approach has been:

most maintainable?

more easily understood?

semantically correct?

i.e. how well does the variable name match the business object and how well does the variable name flow into conversations about the problem being solved?

conducive to being used with code lookup functionality like Intellisense or the various Eclipse based constructs?

答:
For what it's worth, the two factors I give the most value to when naming variables (other than meaning, of course) are

Is it readable, namely how likely is it that I may read it incorrectly or accidentally choose it from an Intellisense list?

How does it sound when spoken?  Can I talk about my variables with out confusing myself, getting tongue-tied or sounding like a Dr. Suess book?

So, for those reasons, AdjustedArea is better than AreaAdjusted ( it just sounds more natural)
SurfaceAreaInner and SurfaceAreaOuter are way better than  AreaInnerSurface and AreaOuterSurface (where the qualifier is actually hidden in the middle of the name), but I may actually prefer InnerSurfaceArea and OuterSurfaceArea, as that's how I would refer to these things if I were a civilian, so to speak, and not a developer.


答:
You're thinking along the right lines.  Most people prefer names they can read in their head and have it sound close to regular English.

However, the fact that you are having difficulty with long lists in intellisense isn't a variable naming problem, it's a class size problem.  When you start needing to differentiate by a prefix, that's a good sign you need to split that prefix off into its own entity somehow.  For example, Container.Area[INNER].  Use the features of the language, that's what they're there for.

Title: Order of subject and modifiers in variable names

Body:
I'm looking for experiences regarding the ordering of the subject and modifiers in variable names.

A simple object Shape would have just a subject for the variable name, such as Area.

A slightly more complex case Sphere which has a wall will have an inner volume and an outer volume, which is where my question comes into play.

What's preferred between Modifier-Subject or Subject-Modifier?

As an example set:

```
class Containers_Modifier_Subject
{
  AreaAdjustmentFactor
  WallThickness
  Height
  Length
  Width
  AdjustedArea
  SurfaceAreaInner
  SurfaceAreaOuter
  LongWallArea
  ShortWallArea
  TopArea
  InnerVolume
  OuterVolume
}

class Containers_Subject_Modifier
{
  AreaAdjustmentFactor
  WallThickness
  Height
  Length
  Width
  AreaAdjusted
  AreaInnerSurface
  AreaOuterSurface
  AreaLongWall
  AreaShortWall
  AreaTop
  VolumeInner
  VolumeOuter
}
```

The trigger for my question comes from an object that is similar to the examples.  There were enough variables in the object that only a portion displays in the code ahead / lookup window from the IDE.  I want to make sure that any future developer is quickly led to the correct variable that they'll be looking for without having to scroll up and down through the lookup window.

In my case, I was looking for the total area, but the area factor and adjusted area values had popped up first.

Consistency in naming as a code standard is a given.

Which naming approach has been:

most maintainable?

more easily understood?

semantically correct?

i.e. how well does the variable name match the business object and how well does the variable name flow into conversations about the problem being solved?

conducive to being used with code lookup functionality like Intellisense or the various Eclipse based constructs?


问:
Should I represent special cases (like errors / exceptions) in UML diagrams?
Let's say you write a program that, when started, reads its configuration file to know which modules to start-up etc. If that configuration file is missing, an error will probably show up. This is an important situation that must always be handled.

I read a statistic once which said that about 70 % of the code in a typical program is there to deal with corner cases (like check that file is not missing, catch an Exception, check that I don't divide by 0, check that a person's age is a positive number etc.).

I don't believe this (i.e. the 70 % claim) to be very accurate, but then again, a lot of the code that I write contains a lot of ifs that check for valid parameters and stuff like that. I doubt I'm the only one who does this. So that statistic does have some truth in it.

If a big part of a program's code is represented by these checks, then shouldn't these cases be represented in UML diagrams ? (like sequence diagrams etc.). I can't remember if I ever saw such things.

Should I include them in my diagrams ? Will that enlighten or disturb/confuse another programmer who looks at those diagrams ? Would the diagrams then become too big because of this ?

答: I don't think so.  UML diagrams don't generally show details that far down.  You might outline your plan for exception handling in pseusocode somewhere, but you don't want to clutter your higher level diagrams with defensive programming details.  I think that would be noisy.</p>


问:
How do you organize highly customized software?
I'm working on a large software project which is highly customized for various customers arround the world. This means that we have maybe 80% code which is common between the various customers, but also a lot of code which has to change from one customer to the other. In the past we did our development in separate repositories (SVN) and when a new project started (we have few, but large customers) created another repository based on whatever past project has the best code basis for our needs. This has worked in the past, but we ran into several problems:

Bugs which are fixed in one repository are not patched in other repositories. This might be a problem of organization, but I find it difficult to fix and patch a bug in 5 different repositories, keeping in mind that the team maintaining this repository might be in another part of the world and we don't have their test environment, neither know their schedule or what requirements they have (a "bug" in one country might be a "feature" in another).

Features and improvements made for one project, which might also be useful for another project are lost or if they are used in another project often cause big headaches merging them from one code base to another (since both branches might have been developed independently for a year).

Refactorings and code improvements made in one development branch are either lost or cause more harm than good if you have to merge all these changes between the branches.

We are now discussing how to solve these problems and so far came up with the following ideas on how to solve this:

Keep development in separate branches but organizing better by having a central repository where general bug fixes are merged into and having all projects merge changes from this central repository into their own on a regular (e.g. daily) basis. This requires huge discipline and a lot of effort for merging between the branches. So I'm not convinced that it will work and we can keep this discipline, especially when time pressure puts in.

Abandon the separate development branches and have a central code repository where all our code lives and do our customization by having pluggable modules and configuration options. We are already using Dependency Injection containers to resolve dependencies in our code and we are following the MVVM pattern in most of our code to cleanly separate business logic from our UI.

The second approach seems to be more elegant, but we have many unsolved problems in this approach. For example: how do handle changes/additions in your model/database. We are using .NET with Entity Framework to have strongly typed entities. I don't see how we can handle properties which are required for one customer but useless for another customer without cluttering our data model. We are thinking of solving this in the database by using satellite tables (having a separate tables where our extra columns for a specifiy entity live with a 1:1 mapping to the original entity), but this is only the database. How do you handle this in code? Our data model lives in a central library which we would not be able to extend for each customer using this approach.

I'm sure that we are not the only team struggling with this problem and I'm shocked to find so little material on the topic.

So my questions are the following:

What experience do you have with highly customized software, what approach did you choose and how did it work for you?

What approach do you recommend and why? Is there a better approach?

Are there any good books or articles on the topic that you can recommend?

Do you have specific recommendations for our technical environment (.NET, Entity Framework, WPF, DI)?

Edit:

Thanks for all the suggestions. Most of the ideas match those that we already had in our team, but it is really helpful to see the experience you had with them and tips to better implement them.

I'm still not sure which way we will go and I'm not making the decision (alone), but I will pass this along in my team and I'm sure it will be helpful.

At the moment the tenor seems to be a single repository using various customer specific modules. I'm not sure our architecture is up to this or how much we have to invest to make it fit, so some things might live in separate repositories for a while, but I think it's the only longterm solution that will work.

So, thanks again for all responses!

答:
It sounds like the fundamental problem is not just code repository maintenance, but a lack of suitable architecture.

What is the core/essence of the system, that will always be shared by all systems?

What enhancements/deviations are required by each customer?

A framework or standard library encompasses the former, while the latter would be implemented as add-ons (plugins, subclasses, DI, whatever makes sense for the code structure).

A source control system that manages branches and distributed development would probably help also; I'm a fan of Mercurial, others prefer Git. The framework would be the main branch, each customized system would be sub-branches, for example.

The specific technologies used to implement the system (.NET, WPF, whatever) are largely unimportant.

Getting this right is not easy, but it is critical for long-term viability. And of course the longer you wait, the greater the technical debt you'll have to deal with.

You may find the book Software Architecture: Organizational Principles and Patterns useful.

Good luck!


答: Microsoft has a long history of coming out with hot new technologies and then forgetting about them 5, 10, or 20 years down the road. LINQ might look like another one to some people. They'll note that Microsoft cannot deprecate SQL, but LINQ could be following Silverlight. So you could be seeing paranoia resulting from hard experience, or just people who've been left behind by modern technology and who resent it.


答:
This argument assumes you have no problem with typing unicodes nor reading greek letters

Here's the argument: would you like pi or circular_ratio?

In this case, I'd prefer pi to circular_ratio because I've learned about pi since I was in grade school and I can expect the definition of pi is well ingrained to every programmers worth his salt. Therefore I wouldn't mind typing π to mean circular_ratio.

However, what about

```<code>winner_sigma_new = ( winner_sigma ** 2 *
                    ( 1 -
                     ( winner_sigma ** 2 -
                       general_uncertainty ** 2
                     ) * Wwin(t,e)
                    ) + dynamics ** 2
                   )**.5
</code>```

or

```<code>σw_new = (σw**2 * (1 - (σw**2)/(c**2)*Wwin(t, e)) + γ**2)**.5
</code>```

To me, both versions are equally opaque, just like pi or π is, except I didn't learn this formula in grade school. winner_sigma and Wwin means nothing to me, or to anyone else reading the code, and using neither σw doesn't make it any better.

So, using descriptive names, e.g. total_score, winning_ratio, etc would increase readability much better than using ascii names that merely pronounce greek letters. The problem isn't that I can't read greek letters, but I can't associate the characters (greek or not) with a "meaning" of the variable.

You certainly understood the problem yourself when you commented: You should have seen the paper. It's just eight pages.... The problem is if you base your variable naming on a paper, which chooses single-letter names for conciseness rather than readability (irrespective whether they're greek), then people would have to read the paper to be able to associate the letters with a "meaning"; this means you're putting an artificial barrier for people to be able to understand your code, and that's always a bad thing.

Even when you live in an ASCII-only world, both a * b / 2 and alpha * beta / 2 are an equally opaque rendering of height * base / 2, the triangle area formula. The unreadability of using single-letter variables grows exponentially as the formula grows in complexity, and the AllegSkill formula is certainly not a trivial formula.

Single letters variable is only acceptable as a simple loop counter, whether they are greek single-letters or ascii single-letter, I don't care; no other variables should consist solely of a single letter. I don't care if you use greek letters for your names, but when you do use them, make sure I can associate those names with a "meaning" without needing to read an arbitrary paper somewhere else.

When in grade school, I definitely wouldn't mind seeing mathematical expressions using symbols such as: +, -, ×, ÷, for basic arithmetics and √() would be a square-root function. After I graduated grade school, I wouldn't mind the addition of a shiny new symbols: ∫ for integration. Note the trend, these are all operators. Operators are much more heavily used than variable names, but they are less often reused for an entirely different meaning (in the case where mathematicians reuse operators, the new meaning often still holds some basic properties of the old meaning; this is not the case for when reusing variable names).

In conclusion, no, it's not bad to use Unicode characters for variable names; however, it's always bad to use single letter names for variable names, and being allowed to use Unicode names is not a license to use single letter variable names.

Title: Is it bad to use Unicode characters in variable names?

Body:
I recently tried to implement a ranking algorithm, AllegSkill, to Python 3.

Here's what the maths looks like:

No, really.

This is then what I wrote:

```<code>t = (µw-µl)/c  # those are used in
e = ε/c        # multiple places.
σw_new = (σw**2 * (1 - (σw**2)/(c**2)*Wwin(t, e)) + γ**2)**.5
</code>```

I actually thought it is unfortunate of Python 3 to not accept √ or ² as variable names.

```<code>>>> √ = lambda x: x**.5
  File "<stdin>", line 1
    √ = lambda x: x**.5
      ^
SyntaxError: invalid character in identifier
</code>```

Am I out of my mind? Should I have resorted for a ASCII only version? Why? Wouldn't an ASCII only version of the above be harder to validate for equivalence with the formulas?

Mind you, I understand some Unicode glyphs look very much like each other and some like     ▄ (or is that ▗▖ ) or ╦  just can't make any sense in written code. However, this is hardly the case for Maths or arrow glyphs.

Per request, the ASCII only version would be something along the lines of:

```<code>winner_sigma_new = ( winner_sigma ** 2 *
                    ( 1 -
                     ( winner_sigma ** 2 -
                       general_uncertainty ** 2
                     ) * Wwin(t,e)
                    ) + dynamics ** 2
                   )**.5
</code>```

...per each step of the algorithm.

Body:
This argument assumes you have no problem with typing unicodes nor reading greek letters

Here's the argument: would you like pi or circular_ratio?

In this case, I'd prefer pi to circular_ratio because I've learned about pi since I was in grade school and I can expect the definition of pi is well ingrained to every programmers worth his salt. Therefore I wouldn't mind typing π to mean circular_ratio.

However, what about

winner_sigma_new = ( winner_sigma ** 2 *
                    ( 1 -
                     ( winner_sigma ** 2 -
                       general_uncertainty ** 2
                     ) * Wwin(t,e)
                    ) + dynamics ** 2
                   )**.5

or

σw_new = (σw**2 * (1 - (σw**2)/(c**2)*Wwin(t, e)) + γ**2)**.5

To me, both versions are equally opaque, just like pi or π is, except I didn't learn this formula in grade school. winner_sigma and Wwin means nothing to me, or to anyone else reading the code, and using neither σw doesn't make it any better.

So, using descriptive names, e.g. total_score, winning_ratio, etc would increase readability much better than using ascii names that merely pronounce greek letters. The problem isn't that I can't read greek letters, but I can't associate the characters (greek or not) with a "meaning" of the variable.

You certainly understood the problem yourself when you commented: You should have seen the paper. It's just eight pages.... The problem is if you base your variable naming on a paper, which chooses single-letter names for conciseness rather than readability (irrespective whether they're greek), then people would have to read the paper to be able to associate the letters with a "meaning"; this means you're putting an artificial barrier for people to be able to understand your code, and that's always a bad thing.

Even when you live in an ASCII-only world, both a * b / 2 and alpha * beta / 2 are an equally opaque rendering of height * base / 2, the triangle area formula. The unreadability of using single-letter variables grows exponentially as the formula grows in complexity, and the AllegSkill formula is certainly not a trivial formula.

Single letters variable is only acceptable as a simple loop counter, whether they are greek single-letters or ascii single-letter, I don't care; no other variables should consist solely of a single letter. I don't care if you use greek letters for your names, but when you do use them, make sure I can associate those names with a "meaning" without needing to read an arbitrary paper somewhere else.

When in grade school, I definitely wouldn't mind seeing mathematical expressions using symbols such as: +, -, ×, ÷, for basic arithmetics and √() would be a square-root function. After I graduated grade school, I wouldn't mind the addition of a shiny new symbols: ∫ for integration. Note the trend, these are all operators. Operators are much more heavily used than variable names, but they are less often reused for an entirely different meaning (in the case where mathematicians reuse operators, the new meaning often still holds some basic properties of the old meaning; this is not the case for when reusing variable names).

In conclusion, no, it's not bad to use Unicode characters for variable names; however, it's always bad to use single letter names for variable names, and being allowed to use Unicode names is not a license to use single letter variable names.


问:
Is an Inner Function Justified in this Situation
I'm new to the functional programming concepts in C#, but I have some experience with higher order functions via Haskell, Scala, Python and Ruby. I'm currently going through an old .NET 2.0 codebase with a LOT of duplication in it. Most of it is simple "copy/paste" with a few variables changed. I'm trying to condense as much of this as possible.

A chunk of code within a routine I'm working on now goes a bit like this, for example:

```<code>if (PostProcess.UsesFirstPass)
{
    w.WriteLine(V1 + " = 0" + " !! SET FOO");
    w.WriteLine(V2 + " = 0" + " !! SET BAR");
    w.WriteLine(V3 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V3 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V4 + " = 0" + " !! SET QUUX");
}
if (PostProcess.UsesSecondPass)
{
    w.WriteLine(V5 + " = 0" + " !! SET FOO");
    w.WriteLine(V6 + " = 0" + " !! SET BAR");
    w.WriteLine(V7 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V7 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V8 + " = 0" + " !! SET QUUX");
}
if (PostProcess.UsesFinalPass)
{
    w.WriteLine(V9 + " = 0" + " !! SET FOO");
    w.WriteLine(V10 + " = 0" + " !! SET BAR");
    w.WriteLine(V11 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V11 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V12 + " = 0" + " !! SET QUUX");
}
</code>```

Where any of the "V"s you see in there is a string variable defined earlier. It's part of a fairly large method. I could write another method called, say, WriteVariables() and pass in the required info and call it three times, but it only ever applies to this section of method. I think this would be a place where writing an anonymous inner function would make sense.

I did it to test it out, and it seems to work fine. Now I have a single delegate that looks something like:

```<code>private delegate void WriteCutVars(string V1,
    string V2, string V3, string V4, CuttingParameters cutParam);

// snip //

WriteCutVars WriteVars = (Va, Vb, Vc, Vd) => {
    w.WriteLine(Va + " = 0" + " !! SET FOO");
    w.WriteLine(Vb + " = 0" + " !! SET BAR");
    w.WriteLine(Vc + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(Vc + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(Vd + " = 0" + " !! SET QUUX");
}
if (Process.UsesFirstPass) WriteVars(V1, V2, V3, V4);
if (Process.UsesSecondPass) WriteVars(V5, V6, V7, V8);
if (Process.UsesFinalPass) WriteVars(V9, V10, V11, V12);
</code>```

My main questions:

Is this a proper use of inner functions?

Is this acceptable when I'm    the only CS graduate on a team of
mostly mechanical engineers?

答:
Your implementation seems reasonable to me.

However, if most of the other people developing the software have limited advanced programming experience you might want to use a regular function instead of an anonymous one since it will be more obvious what's going on.

When you're the senior developer and the rest of your team is at a significantly lower skill level; making sure they understand how your code works and can easily modify it if needed is an important consideration.  Since your team mostly consists of non-programmers this is a larger consideration, since for programming techniques they probably congregate closer to the Use What I Know end of the scale than the Learn New Things Everyday end.

Breaking the repeated logic out and removing the copy/pasting should be simple to explain the benefits of.  More advanced techniques like anonymous functions or linq would be a harder sell since they don't give major and obvious functional/maintenance improvements.  The hardware engineers I've worked with in the past mostly only learned C in college since it was the language of choice for the micro-controllers in the gadgets they were building.  With only a handful of classes their skills were concentrated on practical basic programming only, and not anything advanced.


答:
Doesn't it make sense to pull code "off the shelf" if it accomplishes the same goals without extra cost?

There's always an extra cost.

The learning curve for off the shelf stuff is always there. The pain of getting updates (and dependencies) is always there. The inability to screw around with the guts is always there.

For LINQ, the first only really applies. Many people consider the 'weird' looking code to be hard to read and harder to debug. The sql-like syntax is pretty much persona-non-grata every professional gig I've worked since it came out. LINQ to SQL (and other data sources) have a number of gotchas and limited optimization options.

These are the general arguments against 3rd party tools and LINQ specifically. All that said, LINQ is a damned useful tool and should be preferred in most situations. Crying Not Invented Here, and abstractions should not be favored smacks strongly of Cognative Dissonance.

They don't know/can't learn LINQ, but they're "obviously" good developers, so LINQ must not be worthwhile. It's a common trap.


答:
This is not a higher-order function, so it should be easily understandable to any C# programmer.

Although instead of using a custom delegate type, you could've used Action<string, string, string, CuttingParameters>.

But I think a normal method would have been fine here too, and is probably more idiomatic. Even if you won't use it anywhere else.

Title: Is an Inner Function Justified in this Situation

Body:
I'm new to the functional programming concepts in C#, but I have some experience with higher order functions via Haskell, Scala, Python and Ruby. I'm currently going through an old .NET 2.0 codebase with a LOT of duplication in it. Most of it is simple "copy/paste" with a few variables changed. I'm trying to condense as much of this as possible.

A chunk of code within a routine I'm working on now goes a bit like this, for example:

```<code>if (PostProcess.UsesFirstPass)
{
    w.WriteLine(V1 + " = 0" + " !! SET FOO");
    w.WriteLine(V2 + " = 0" + " !! SET BAR");
    w.WriteLine(V3 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V3 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V4 + " = 0" + " !! SET QUUX");
}
if (PostProcess.UsesSecondPass)
{
    w.WriteLine(V5 + " = 0" + " !! SET FOO");
    w.WriteLine(V6 + " = 0" + " !! SET BAR");
    w.WriteLine(V7 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V7 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V8 + " = 0" + " !! SET QUUX");
}
if (PostProcess.UsesFinalPass)
{
    w.WriteLine(V9 + " = 0" + " !! SET FOO");
    w.WriteLine(V10 + " = 0" + " !! SET BAR");
    w.WriteLine(V11 + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(V11 + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(V12 + " = 0" + " !! SET QUUX");
}
</code>```

Where any of the "V"s you see in there is a string variable defined earlier. It's part of a fairly large method. I could write another method called, say, WriteVariables() and pass in the required info and call it three times, but it only ever applies to this section of method. I think this would be a place where writing an anonymous inner function would make sense.

I did it to test it out, and it seems to work fine. Now I have a single delegate that looks something like:

```<code>private delegate void WriteCutVars(string V1,
    string V2, string V3, string V4, CuttingParameters cutParam);

// snip //

WriteCutVars WriteVars = (Va, Vb, Vc, Vd) => {
    w.WriteLine(Va + " = 0" + " !! SET FOO");
    w.WriteLine(Vb + " = 0" + " !! SET BAR");
    w.WriteLine(Vc + " = 0" + " !! SET BAZ");
    if (PostProcess.IsSpecial){
        w.WriteLine(Vc + " = 20" + " !! INCREASE BAZ");
    }
    w.WriteLine(Vd + " = 0" + " !! SET QUUX");
}
if (Process.UsesFirstPass) WriteVars(V1, V2, V3, V4);
if (Process.UsesSecondPass) WriteVars(V5, V6, V7, V8);
if (Process.UsesFinalPass) WriteVars(V9, V10, V11, V12);
</code>```

My main questions:

Is this a proper use of inner functions?

Is this acceptable when I'm    the only CS graduate on a team of
mostly mechanical engineers?


答:
I think you're making some mad generalisations there of the "I saw a black cow in Scotland, so all Scottish cows are black" type.

If I interviewed you I'd be disappointed if you couldn't answer my linq questions.

Linq is a tricky one though, a lot of people see it as voodoo which is unfair as it's actually very simple and all the more clever for it.


答:
Using an old language sounds all rosy; sometimes we almost have a nostalgic appreciation for languages we used earlier in our lives.  Like a house we lived in when we were young.  This is my analogy and answer.

The things that caused me to move out of my parents house when I was 18 aren't easily remembered.  But if I moved back in, the rosy appreciation and nostalgia would wear off quickly.  I would remember the shower near my room with poor pressure.  The limey poorly softened well water.  The inability to bring a girl over without my dad engaging them in a philosophical expose about their purpose in life.

And just as a side note... Java is to you as PHP is to me.  I also moved to Python.  Using a tool you don't HAVE to use causes your task to be missing a key component.  I call it the "Bridge of Necessity".  This bridge caries us across rivers that we lack the courage, motivation, or ambition to cross ourselves.  Always approach a project with a bridge of necessity.  Often I make promises to friends like "In a week I will have this cool demo to show you".  This forces me to get off my ass and program the cool thing I was spouting off about or otherwise be a liar.  You don't want to be a liar do you, DO YOU?

:)

Title: When you won't need a language anymore, should you still use it?

Body:
My first main language was Java.  However, over the years I've dropped Java in favor for Python, JavaScript, bash, etc.  I still have advanced reading knowledge of Java, but since I haven't coded in it for so long, my writing knowledge is intermediate at most.  The other day, while looking at some old code written in Java, I got inspiration to re-write it as a learning experience to reacquaint myself.

It was at that point that I stopped to think that if I wrote this in Java, it would be nice, but when the renewed inspiration had hit me, I wanted to implement it as a web app (it was a game), so other people could play it.

So now here's the dilemma: Do I re-write (and heavily refactor) the code I've previously written in Java, and then in JavaScript (for the web version), or do I just forget about Java altogether and re-write it in JavaScript?

EDIT: I have no problem writing in Java first and then JavaScript, but I'm more likely than not going to need Java anymore for a long while.  What I'm trying to ask is whether or not I should rewrite the old code in Java first, to practice a skill I may not need in the future.  The actual languages are less important than that question.


问:
Why is Java the lingua franca at so many institutions?
EDIT: This question at first seems to be bashing Java, and I guess at this point it is a bit. However, the bigger point I am trying to make is why any one single language is chosen as the one end all be all solution to all problems. Java happens to be the one that's used so that's the one I had to beat on here, but I'm not intentionality ripping Java a new one :)

I don't like Java in most academic settings. I'm not saying the language itself is bad -- it has several extremely desirable aspects, most importantly the ability to run without recompilation on most any platform. Nothing wrong with using the language for Your Next App ^TM. (Not something I would personally do, but that's more because I have less experience with it, rather than it's design being poor)

I think it is a waste that high level CS courses are taught using Java as a language. Too many of my co-students cannot program worth a damn, because they don't know how to work in a non-garbage-collected world. They don't fundamentally understand the machines they are programming for. When someone can work outside of a garbage collected world, they can work inside of one, but not vice versa. GC is a tool, not a crutch. But the way it is used to teach computer science students is a as a crutch.

Computer science should not teach an entire suite of courses tailored to a single language. Students leave with the idea that all good design is idiomatic Java design, and that Object Oriented Design is the ONE TRUE WAY THAT IS THE ONLY WAY THINGS CAN BE DONE. Other languages, at least one of them not being a garbage collected language, should be used in teaching, in order to give the graduate a better understanding of the machines.

It is an embarrassment that somebody with a PHD in CS from a respected institution cannot program their way out of a paper bag.

What's worse, is that when I talk to those CS professors who actually do understand how things operate, they share feelings like this, that we're doing a disservice to our students by doing everything in Java. (Note that the above would be the same if I replaced it with any other language, generally using a single language is the problem, not Java itself)

In total, I feel I can no longer respect any kind of degree at all -- when I can't see those around me able to program their way out of fizzbuzz problems.

Why/how did it get to be this way?

答: Calvin college in Grand Rapids Mi.  Once they switched from Java to Python for introductory programming classes the professor in disbelief mentioned to a group of us near the end of his semester, "A lot of them can actually program, it's incredible".  His amazement was in contrast to the previous experiences with Java.  This doesn't make Java a bad language, just hard to pick up from scratch.  I would argue the same thing about C, or C++ or any language that requires intimate knowledge of memory allocation schemes or types.</p>


问:
What syntax element do you hate most in a programming language you use frequently?
No matter how much you love a programming language, there are always a few details in it that aren’t quite as nice as they could be.

In this question, I would like to specifically focus on syntax elements. In a programming language that you use frequently (perhaps your favourite programming language, or perhaps the one you are forced to use at work), which syntax element do you find most unreadable, unclear, inconvenient or unpleasant?

答:
\we\wouldnt\fix\our\parser namespace syntax in PHP

The syntax is not only ugly, it leads to confusion when newer developers have to think about namespaces in strings.  (PHP interpolates backslashes in double-quoted strings as escape sequences.  Trying to represent a namespace like \you\should\never\do\that in a double-quoted string instead of a single-quoted string will lead to newlines, tabs and disaster.)

OwnerDisplayName: mario


问:
Are there any theories or books about how to debug "in general"?
I read and studied a lot of computer science and engineering and I rarely or never seen a book about debugging or a theory how to debug (though I surely developed some debugging theories of my own).

Are there any debugging theories and/or books? Why / why not? I can read how to debug using gdb and some of the most useful info about development I got from reading how to use gdb.

答:
There is Debugging: The 9 Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems. I don't remember it to be terribly deep or at all academic, but it certainly has some interesting insights and stories.

It's also very useful to see debugging from the hardware perspective--generally, debugging hardware is more difficult than debugging software. Each chapter of the book is motivated by a "war story" from the author's experience; the rest of the chapter goes over what technique he found useful in that particular case. The stories are a nice mix of both hardware and software development.

I certainly found the approach of starting each chapter with a real-life story very instructive.


答:
The key question is whether to use a "normal" private function or a strictly local function and the answer should stem from the same decision-making you'd use with a private field vs. a local variable: Is this thing useful anywhere but this function? In this case, it would appear not, so your approach seems correct.

There is an issue with using advanced functional techniques in C#, but C# is evolving to have more and more functional features, so you ought not avoid all functional techniques only because they may still be unfamiliar. I would say that this would actually be the type of use that would be good in a codebase where people were relatively unfamiliar with functional programming, since it is very straightforward in both utility and implementation.