问:
How do you keep track of large projects?
When dealing with a project that has many different files, I always seem to loose track of how the parts interact with one another. I've never really had much of a problem understanding smaller components in isolation, but as the complexity of the project increases, I find myself unable to mentally construct an understanding of what is going on. I notice this especially with OOP projects, as the number of methods and source files increase.

My background:
I'm a self-taught web programmer. I've dealt mostly with python for quick and dirty scripts, but I've also done a few basic django projects. I like web frameworks such as flask, because in the simplicity of a single-file layout, I can easily keep track (mostly) of what is going on.

I now find myself in a situation where I need to interact with a large Zend Framework PHP project that someone else developed, and I'm overwhelmed with trying to understand the code spread out to numerous files.

What techniques and processes have you found useful to understand a large code base that someone else has developed? Is there any particular diagram that you find helps you grasp the larger picture?

答:
If you're working with something really big with zero documentation (I've been there too, it's rough!), what I've found that helps is to try to isolate the part you're working on.   In that part of the code, figure out how data/events/messages/interactions pass in and out of that unit.  In other words, reverse engineer the interface.  Write it down.  Next time you work on another unit (bonus if it talks to the one you worked first), do the same thing.  Keep all your documentation.  After a few months of this you'll have a nice picture of how the thing flows.

Figure out the interface of one small unit which you are working on, and record it for later reference.  Over time you will stitch together most of how it works.  Find what your program does and trace how that message flows.  For example, if your system takes some input network message and sends an output message, trace how that message flows through the system, without worrying about all the details- just see where it goes.


问:
Stuff every programmer needs while working
I've been tasked with creating a fun and relaxing environment, one thing I know that I want is ergonomic mice and keyboards, others have suggested exercise balls and bands.

What is it that every programmer needs while working? What might not be necessary but would be nice to have anyway?

Note: this question was asked previously, but has been recommended to be posted here. See this link for the previous responses: https://stackoverflow.com/questions/3911911/stuff-every-programmer-needs-while-working-closed

答:
Windows that you can open.

Not the software kind.  The wood/metal frames with glass you look through to see the outside world.

I hate being completely enclosed in a sterile office.  I've been a dual-monitors guy since the 1990's, and I live in Seattle, but I'd give up free coffee and half of my display area to have fresh air in the summer.

ContentLicense: CC BY-SA 2.5

OwnerDisplayName: Ken


问:
Best way to get programmers to ask for help when they get stuck
What is the best way to ensure that programmers ask for help when they get stuck on a problem, rather than spending too much time trying to figure something out when they've hit a wall?

I'm especially interested in how to optimize this with a distributed team.

Some ideas that come to mind:

pair programming

co-locating the team

timeboxes (after expiration, must ask for help)

Things (goals) to think about:

avoid developing dependence on others

maximize learning & knowledge transfer

cost of developer A's time to help vs. developer B's time to figure it out him/herself

There is also the concern that even if a developer comes up with a solution, it may be of lower quality than if they had asked for help.  I believe code reviews are a good way to address this.

This question: When do you not give help to less experienced programmers? is good background reading for this one.

答:
Daily scrum meeting.

Works wonders.  And you have to do it anyway.  More than a day stuck is a serious obstacle that must be addressed.

[BTW: "avoid developing dependence on others" is a terrible objective.  Why bother?  Also "cost of developer A's time to help vs. developer B's time" is a false optimization.]

ContentLicense: CC BY-SA 3.0


问:
Designing my password class(es). How to split it up?
I've inherited a custom made authentication system that needs some refactoring.  I'm not quite sure what the best way to split it up the password section and could use some help.

The password class(es) need the following functionality:

Check to see if a password conforms to restrictions. It needs to be able to provide feedback on why it is incorrect.

Generate three kinds of hashes.  We have several file-systems with incompatible hashes, so unfortunately I have to maintain three hashes.

Give a different hash for a certain user type. If a user is web-only we do not keep a password for them as they cannot use the system.  Their passwords are always *.

Be able to verify a password for a given user. Fortunately I only have to authenticate against one of the three hashes I have to maintain.

Be able to generate a random password, unencrypted.

Submit new password to the database.

I'm thinking about using four classes, Validator, Hasher, Generator, and Changer.

Validator

isCurrentPassword(int userid, string password): bool

getViolations(string password): array

Generator

generate(int length):string Creates a password.

Hasher

hash_*(string password): string where * is the hash type.  I'll have four hashing functions.

Changer

change(int userid, string password):void; throws database exceptions

What would you recommend and why?

答: Who else is supposed to use this authentication system? If it is only your application, use the simplest code possible that can be understood, maintained and tested.  However, I don't see that you should use 2 separate classes as in method 1, because Validator is not a class it is strictly a method of some class. The same goes for Generator.</p>


问:
Computer security expert using pre-made tools or own?
As a digital security consultant when is it 'ok' to use tools someone else made (dumb to reinvent the wheel, right?) and when should I make my own?</p>

答:
If it ain't broke, why fix it?

If it's broke, contribute to the project and help fix it for everyone else too.


答:
Making bad tools is easy, especially in the security arena. Making good tools is actually quite difficult and requires a deep understanding of the problem at hand.

I would say stick with the pre-made tools until you know enough to actually improve them or replace them with something better. I've been in computing for almost 40 years, and I know that my understanding of most security threats is not good enough to "go it alone."

Title: Computer security expert using pre-made tools or own?

Body: As a digital security consultant when is it 'ok' to use tools someone else made (dumb to reinvent the wheel, right?) and when should I make my own?</p>


问:
Is there an IDE for python that creates the same kind of reflective environment that Smalltalk provides?
As anyone who has used Smalltalk knows, one of the main benefits (other than a late-bound language that discourages many poor practices), is that the system is totally transparent and reflective, which makes understanding APIs and existing code easy, and locating functionality pretty easy.

Is there anything that creates a similar environment for Python?

A few examples of features of a smalltalk development environment, not natively found in python are:

search class/method/etc names,

examine inheritance hierarchies

functionality to show the full interface of a given class/object, and where the properties therein originate

an integrated graphical debugger which allows one to examine the full state of everything in the system, and see every instance of a given type, as well as all threads.

Note that I use windows, so anything that works well on windows would be particularly useful.

答: I sometimes find myself using PythonWin's IDE just for the gui available during debugging (run using 'Step-through in the debugger' then show the Stack View).  I've never touched smalltalk, though, so I might be way off base...


答:
My two cents from my own experience:

No programmer ever gets stuck. They just tend to go off on tangents. Research and development tangents.

The best way to ensure that they don't go off on tangents is to separate the role of the lead programmer from the role of the manager: the lead programmer is usually someone very gifted who would rather be coding than managing other programmers. The manager needs to be someone who does little, if any, coding, and his job is to be constantly coaching the team.

That's because when left on their own, programmers tend to be oriented exclusively towards the engineering aspect of their jobs, (engineering lust?) with relative disregard towards project goals. So, it helps to have someone reminding them that there is a project to complete.

Title: Best way to get programmers to ask for help when they get stuck

Body:
What is the best way to ensure that programmers ask for help when they get stuck on a problem, rather than spending too much time trying to figure something out when they've hit a wall?

I'm especially interested in how to optimize this with a distributed team.

Some ideas that come to mind:

pair programming

co-locating the team

timeboxes (after expiration, must ask for help)

Things (goals) to think about:

avoid developing dependence on others

maximize learning & knowledge transfer

cost of developer A's time to help vs. developer B's time to figure it out him/herself

There is also the concern that even if a developer comes up with a solution, it may be of lower quality than if they had asked for help.  I believe code reviews are a good way to address this.

This question: When do you not give help to less experienced programmers? is good background reading for this one.


问:
How to verify/prove orthogonality of a programming language?
I know the concept of orthogonality, but from a programming language point of view, is there a way to verify/prove it?

For instance in C#, one can use public or static for a method signature. You can use either or both and they wouldn't interfere with each other, so they are orthogonal to each other, right?

My question is, how do I go about the rest of features, particularly features that are not related to each other?

Do all the features have to coexist/stack together?

Is there a programming language that is 100% orthogonal?

答:
The term "orthogonality" is a layman's term for a precise mathematical notion: the language terms form an initial algebra (look it up in Wikipedia).

It basically means "there is a 1-1 correspondence between syntax and meaning". This means: there is exactly one way to express things, and, if you can put some expression in a particular place, then you can put any other expression there too.

Another way to think about "orthogonal" is that the syntax obeys the substitution principle. For example if you have a statement with a slot for an expression, then any expression can be put there and the result is still a syntactically valid program. Furthermore, if you replace

I want to emphasise that "meaning" does not imply computational result. Clearly, 1 + 2 and 2 + 1 both equal 3. However the terms are distinct, and imply a different calculation even if it has the same result. The meaning is different, just as two sort algorithms are different.

You may have heard of "abstract syntax tree" (AST). The word "abstract" here means precisely "orthogonal". Technically most AST's are not in fact abstract!

Perhaps you have heard of the "C" programming language? C type notation is not abstract. Consider:

```<code>int f(int);
</code>```

So here is a function declaration returning type int. The type of a pointer to this function is given by:

```<code>int (*)(int)
</code>```

Note, you cannot write the type of the function! C type notation sucks bigtime! It isn't abstract. It isn't orthogonal. Now, suppose we want to make a function which accepts the above type instead of int:

```<code>int (*) ( int (*)(int) )
</code>```

All ok .. but .. what if we want to return it instead:

```<code>int (*)(int) (*) (int)
</code>```

Woops! Invalid. Lets add parens:

```<code>(int (*)(int)) (*) (int)
</code>```

Woops! That doesn't work either. We have to do this (it's the only way!):

```<code>typedef int (intintfunc*) (int);
intintfunc (*)(int)
</code>```

Now its OK, but having to use a typedef here is bad. C sucks. It isn't abstract. It isn't orthogonal. Here's how you do this in ML, which is:

```<code> int -> (int -> int)
</code>```

We condemn C at the syntax level.

Ok, now lets flog C++. We can fix the stupidity above with templates and get an ML like notation (more or less):

```<code>fun<int, int>
fun< fun<int,int>, int>
</code>```

but the actual type system is fundamentally flawed by references: if T is a type, then is T& a type? The answer is waffly: at the syntax level, if you have a type U = T&, then U& is allowed but it just means T&: a reference to a reference is the original reference. This sucks! It breaks the uniqueness requirement semantically. Worse: T& & is not allowed syntactically: this breaks the substitution principle. So C++ references break orthogonality in two different ways, depending on the binding time (parsing or type analysis). If you want to understand how to do this right .. there's no problem with pointers!

Almost no real languages are orthogonal. Even Scheme, which pretends great clarity of expression, isn't. However many good languages can be judged to have a "reasonably close to orthogonal feature basis" and that is a good recommendation for a language, applied both to the syntax and to the underlying semantics.

OwnerDisplayName: Joan Venge

Body:
The term "orthogonality" is a layman's term for a precise mathematical notion: the language terms form an initial algebra (look it up in Wikipedia).

It basically means "there is a 1-1 correspondence between syntax and meaning". This means: there is exactly one way to express things, and, if you can put some expression in a particular place, then you can put any other expression there too.

Another way to think about "orthogonal" is that the syntax obeys the substitution principle. For example if you have a statement with a slot for an expression, then any expression can be put there and the result is still a syntactically valid program. Furthermore, if you replace

I want to emphasise that "meaning" does not imply computational result. Clearly, 1 + 2 and 2 + 1 both equal 3. However the terms are distinct, and imply a different calculation even if it has the same result. The meaning is different, just as two sort algorithms are different.

You may have heard of "abstract syntax tree" (AST). The word "abstract" here means precisely "orthogonal". Technically most AST's are not in fact abstract!

Perhaps you have heard of the "C" programming language? C type notation is not abstract. Consider:

int f(int);

So here is a function declaration returning type int. The type of a pointer to this function is given by:

int (*)(int)

Note, you cannot write the type of the function! C type notation sucks bigtime! It isn't abstract. It isn't orthogonal. Now, suppose we want to make a function which accepts the above type instead of int:

int (*) ( int (*)(int) )

All ok .. but .. what if we want to return it instead:

int (*)(int) (*) (int)

Woops! Invalid. Lets add parens:

(int (*)(int)) (*) (int)

Woops! That doesn't work either. We have to do this (it's the only way!):

typedef int (intintfunc*) (int);
intintfunc (*)(int)

Now its OK, but having to use a typedef here is bad. C sucks. It isn't abstract. It isn't orthogonal. Here's how you do this in ML, which is:

 int -> (int -> int)

We condemn C at the syntax level.

Ok, now lets flog C++. We can fix the stupidity above with templates and get an ML like notation (more or less):

fun<int, int>
fun< fun<int,int>, int>

but the actual type system is fundamentally flawed by references: if T is a type, then is T& a type? The answer is waffly: at the syntax level, if you have a type U = T&, then U& is allowed but it just means T&: a reference to a reference is the original reference. This sucks! It breaks the uniqueness requirement semantically. Worse: T& & is not allowed syntactically: this breaks the substitution principle. So C++ references break orthogonality in two different ways, depending on the binding time (parsing or type analysis). If you want to understand how to do this right .. there's no problem with pointers!

Almost no real languages are orthogonal. Even Scheme, which pretends great clarity of expression, isn't. However many good languages can be judged to have a "reasonably close to orthogonal feature basis" and that is a good recommendation for a language, applied both to the syntax and to the underlying semantics.


答:
Check to see if a password conforms to restrictions

I think this belongs in its own class. In your method 1, you've got it as part of the Validator class. But it doesn't have the same dependencies as isCurrentPassword or share any implementation details. As a result, I'd put in a seperate PasswordAudit class.

Generate three kinds of hashes

You should have some sort of interface which provides uniform access to the different filesystems you are using. I'd suggest the hash() function should live there. Its an implementation detail of the filesystem, and belongs in your handling for that filesystem

Give a different hash for a certain user type

If they can't use the system, why do they have accounts? Or perhaps they can login into the web system, but don't have access to the filesystem backends? But in that case, they'd still have a password wouldn't they?

I'd suggest implementing this by a NullFileSystem backend. The backend would support the interface of a filesystem, but not actually work. Overriding the hash is easily done.

Be able to verify a password for a given user.

I'd be inclined to use the user object for this purpose. It would have an authenticate method which determines whether the given password matches the user object.

Of course, I've only got a glimpse of what you are doing, so my suggestions may or may not make any sense.

Title: Designing my password class(es). How to split it up?

Body:
I've inherited a custom made authentication system that needs some refactoring.  I'm not quite sure what the best way to split it up the password section and could use some help.

The password class(es) need the following functionality:

Check to see if a password conforms to restrictions. It needs to be able to provide feedback on why it is incorrect.

Generate three kinds of hashes.  We have several file-systems with incompatible hashes, so unfortunately I have to maintain three hashes.

Give a different hash for a certain user type. If a user is web-only we do not keep a password for them as they cannot use the system.  Their passwords are always *.

Be able to verify a password for a given user. Fortunately I only have to authenticate against one of the three hashes I have to maintain.

Be able to generate a random password, unencrypted.

Submit new password to the database.

I'm thinking about using four classes, Validator, Hasher, Generator, and Changer.

Validator

isCurrentPassword(int userid, string password): bool

getViolations(string password): array

Generator

generate(int length):string Creates a password.

Hasher

hash_*(string password): string where * is the hash type.  I'll have four hashing functions.

Changer

change(int userid, string password):void; throws database exceptions

What would you recommend and why?


答:
The best security tools are the ones which are transparent, open source and used and reviewed by lots of experts.

So for example PGP encryption is used by lots of people and hs been reviewed by lots of experts. It would be a bad decision to use some home encryption algorithm that you wrote yourself simply because they would not be reviewed and tested by a wide viriety of independent experts.


答:
I'll contribute another two cents to this...

Happy Hour.

First off, I'll just say that I really don't know the answer as we've had similar circumstances.  But it seems at the root, the issue is communications. Anything you can do to help the team communicate better and more efficiently will help. As people start talking more and more with each other, they will not be nearly as reluctant about popping off a quick instant message just to ping someone else and see if they know what the solution is.  On the other hand, when your team feels like they are a bunch of strangers thrown into the same team, their communications will be very limited and some would feel that if they ask a lead or anyone else for help, they'd be "bothering" them.

And I know it can be even more difficult with distributed teams. I'm kinda stranded across two different teams.  In each team, we have an out of state developer. The interesting part is that the two teams feel very different when I interact with others team members.  What I noticed is that in a "better" (don't know if that's a good word, they are all good guys) team, we have a lot more random conversations.  We'll talk about snow, snakes, burgers....  On the other team, everything is way too non-personal and effects of that seem to spill over into professional communications as well.  We don't have as many random meetings, or chat sessions and when we do talk, everyone tries to steer clear and be careful and reserved.

As I do believe alcohol is a solution to many problems, one of my short term goals is to hop on a plane with some of the other team members and just go have a beer with the two out-of-state guys. Maybe it'll work or maybe I'll be posting a different answer on SE in the future.

The bottom line is do whatever you can to improve communications:

Try to get people to socialize in non-work setting (i.e. what I already said above)

Promote pair programming or at least collaboration whenever it makes sense.  I know some will balk at the idea of always being tied to another developer so this may not be for everyone.

Co-location, if possible, definitely helps but is it always possible?

As S.Lott pointed out, stand-ups will definitely promote team communications

Random check ins -- sometimes even in daily stand-ups people will report their task is going "fine", but when you just pop into their cube, you might find out they are stuck on something for the last 3 hours.

Invest in better communications software.  We have instant messaging and I still feel even that makes people too detached.  We've been throwing around ideas of giving everyone web cams.

Informal, no management, meetings to talk about what's on peoples minds. How they feel the project is going, where are you lacking, potential problem areas to watch out for. This is kind of like Agile retrospective, but at least the way we've been doing those, it seems it is too formal and often people are told to stop talking because there's an agenda.  While that type of meeting helps to move things forward and we do make progress in terms of retrospective, it seems to squash some of the desire to communicate.

Lastly, code reviews definitely help and you should introduce them and ensure that they are done regularly.  They are another communications point for your team.  However, you will recognize many similar problems in code reviews that you see now.  A lot of times, there would be a better solution but by the time code review rolls around it's already been coded and you don't feel like making people rework what was done.  Would be nice to get them to talk before they go down some path in the first place.


问:
What is the difference between a pointer pointing to 0x0 location and a pointer set to NULL?
Is a pointer pointing to 0x0000 the same as a pointer set to NULL? If NULL value is defined in the C language, then what location does it physically translate to? Is it the same as 0x0000. Where can I find more details about these concepts?</p>

答:
A point that most of the answers here are not addressing, at least not explicitly, is that a null pointer is a value that exists during execution, and a null pointer constant is a syntactic construct that exists in C source code.

A null pointer constant, as Karlson's answer correctly states, is either an integer constant expression with the value 0 (a simple 0 is the most common example), or such an expression cast to void* (such as (void*)0).

NULL is a macro, defined in <stddef.h> and several other standard headers, that expands to an implementation-defined null pointer constant.  The expansion is typically either 0 or ((void*)0) (the outer parentheses are needed to satisfy other language rules).

So a literal 0, when used in a context that requires an expression of pointer type, always evaluates to a null pointer, i.e., a unique pointer value that points to no object.  That does not imply anything about the representation of a null pointer.  Null pointers are very commonly represented as all-bits-zero, but they can be represented as anything.  But even if a null pointer is represented as 0xDEADBEEF, 0 or (void*)0 is still a null pointer constant.

This answer to the question on stackoverflow covers this well.

This implies, among other things, that memset() or calloc(), which can set a region of memory to all-bits-zero, will not necessarily set any pointers in that region to null pointers.  They're likely to do so on most implementations, perhaps even all existing ones, but the language doesn't guarantee it.

This question is really a duplicate of this one, but Stack Exchange doesn't allow marking duplicates across sites.

ContentLicense: CC BY-SA 4.0


答:
One thing that has not been mentioned is the pomodoro technique of scheduling breaks during the work day.

www.pomodorotechnique.com

Just getting up and getting a drink of water or having a chat with someone else can be very helpful to "reset" the brain and look with somewhat fresher eyes. All other options here are great. I thought I would add this as it has helped me lots.

As a side benefit, time tracking is easier as it is now just "how many tomatoes did that take?" Multiply that by 25 and you have your answer. :)


问:
LGPL open source license
I have recently become curious about open source licenses. I have a question about the LGPL. I created a Java web project and built it as a WAR package. Can I add LGPL jars to this WAR file?</p>

答:
Warning: I am not a lawyer.  If you need legally sound advice, always ask a lawyer.  In this case, ask a lawyer who understands open source licensing.

The following is a summary:

If you don't distribute the WAR file to anyone else, then LGPL places no restrictions on what you do with the library.

If you do distribute the WAR file to someone else, you have two options:

Release your source code under a license that is compatible with the GPL or LGPL, OR ...

Use the LGPL'ed libraries in your code without modifying the libraries, AND without linking or incorporating the libraries into your code in a way that prevents the recipient from replacing them with a modified copy of the libraries.

(Assuming that the library in question is Java, option 2 means that you have to use the library JAR file as-is.  Don't add your own customizations / fixes, don't change class or package names (etc), don't add classes, and don't merge it with your own JAR files.)

For more information, please refer to the GNU Lesser Public License page.

OwnerDisplayName: Kevin Shen

Title: LGPL open source license

OwnerDisplayName: Stephen C


答: If you do them, sharing time estimate with the team can help.  I am not really talking about "timeboxing" either.  Rather, I will tell one of my minions that I think a task should take X hours/days.  If they start on the task, and realize they are not making enough progress as they approach X, then they know that they need to reach out.  The flip side of this is that you need to do the same thing for yourself, which demonstrates to the team that you are meeting your goals and helps reinforce that you are estimating accurately and can offer sound advice for tackling a problem.</p>


问:
Best practices for team workflow with RoR/Github for designer + coder?
My friend and I have started to try to collaborate on some projects. For background, I come from a PHP/Wordpress/Drupal coding background, but recently I've become more experienced with the RoR framework, while he is more experienced as an HTML/CSS designer, working with PHP and WordPress.

We're both relatively new to RoR I think, and so we're trying to figure out our collaborative workflow, but we have no idea where to start.

For instance, we were trying to figure out how he could do some minor edits to the CSS file without having to do a full RoR deploy on his box. We still haven't figured out a solution, so I think it's best if we start to set some sort of workflow based on best practices.

I was wondering if you guys have any insight or links to articles/case studies regarding this topic?

答:
(before the question goes away) you'll need to setup Rails on his machine if you want him to work on the views in their native language (Haml, Erb, etc.) if you don't want to he'll have to work on pure HTML and you'll have to adapt everything he does (not recommended).

as for git, the most common approach is "topic branches" that is, use a new branch for each feature and merge everything to master.

OwnerDisplayName: Josh


问:
Evidence of Bad Design: Updating feature A breaks/interferes with existing feature B
I am working on a Javascript Web App & I am finding as I expand the program & add new features(new animations) it causes existing features to break or work differently than prior to adding that new feature. So as I continue to finish the app, it keeps breaking old features & I have to go back & redo/update those features. So it seems I never complete a feature because I am always coming back to it so I can get it to work nicely with other features.

Is this indicative of bad application design? Or is this a normal feature of computer programming, ie just like how in any program you will spend 20% of time developing the program & 80% of the time fixing bugs(or is it maintaining the program?)?

Are there design &/or any other techniques I can employ to avoid having this problem occur?

The application is a renderer (which takes an XML file which contains information about objects that perform animations - move around, fade etc.) that creates HTML elements & animates them.

The design is OOP, with as close as you can get to classes in Javascript by using prototype. It employs ALOT of multiple inheritence. It also makes use of the anonymous functions where possible so I think it would be very much like a Java project because they both have OOP, anon functions & inheritence. There is a class purely dedicated towards animation called AnimatedObject & many objects inherit from this class. You just perform an animation by simply calling a function from that class such as myAnimObj.performFade() or myAnimObj.performRotate().

答:
From what you describe, it seems that old code depends on more recent code.

Normally, recent, less stable components, should depend on older, more stable components, not vice versa.

Check your design and make sure the latter does not occur.

An easy technique is to draw a diagram and visualize the dependencies with arrows. If you notice that a stable component depends on an unstable one, consider applying techniques like dependency inversion.


问:
Strictly from an employability perspective, what is the best web development framework to learn right now?
Even though Ruby on Rails seems to be the most popular with the most job openings, is there a compelling employability reason to learn django for example?  Maybe because everybody's learning RoR and there's a shortage of django developers in relation to the demand?  Or is php along with a popular php framework the way to go simply because of the sheer volume of php related jobs out there?</p>

答: You'll have to look at the job listings in your local area, everywhere is different. And I would say that if Ruby on Rails is "the most popular with the most job openings" where you are, then your location is more different than most! </p>


答:
It depends on many factors

Your location

Firms that you want to work for

Kind of web application these firms are building

And even all of these wont point you to that one holy grail.

Learn what you like most and think you can accomplish your tasks with.

Title: Strictly from an employability perspective, what is the best web development framework to learn right now?

Body: Even though Ruby on Rails seems to be the most popular with the most job openings, is there a compelling employability reason to learn django for example?  Maybe because everybody's learning RoR and there's a shortage of django developers in relation to the demand?  Or is php along with a popular php framework the way to go simply because of the sheer volume of php related jobs out there?</p>


问:
Emphasizing the importance of TDD to customers
The importance of TDD needs to be propagated but there's always a gap in the project timeline and time needed for developing a TDD project.  Customers usually do not understand the importance of code maintenance or TDD and want the project to be finished as soon as possible.

The result would be a Test After Development which would be very basic minimal tests to please the coverage tools and let the project analyzers have a great Graph.

Do projects developed using TDD take longer, or is that just an unfounded fear?

答: TDD is of course a better methodology for making the project timeline shorter. It also helps the developer to move towards meeting the customer's requirements for the product functionality.</p>


问:
Do people in non-English-speaking countries code in English?
I've heard it said (by coworkers) that everyone "codes in English" regardless of where they're from. I find that difficult to believe, however I wouldn't be surprised if, for most programming languages, the supported character set is relatively narrow.

Have you ever worked in a country where English is not the primary language?

If so, what did their code look like?

答:
Once I've worked with code which was written by Italian programmers, and once by German programmers. It was standard MFC/C++, so of course all the keywords and language/platform was in English. But the variable names, classes, functions, and inline comments were in Italian and German, respectively.

It's amazing how much difference that makes in terms of readability and ease of maintenance.

On the flipside, I can imagine that as a non-English speaker, it would be quite a steep learning curve to learn a programming language/platform where all the keywords and APIs are in English. Even if all the documentation is translated and you can look it up.


问:
How exactly do we go from Binary/Hex to Assembly Instruction sets?
So i've been trying to learn some Embedded/Assembly programming for a bit here lately, as well as going far as trying to learn the lowest level (gates and such).

One thing puzzles me though....is how do we "get" instruction sets. I understand somewhat how gates/TTL and such works, but I don't see how we get from that to mov,add,clr etc...?

It's probably a stupid question....but I mean I think back to the first micro-processors/controllers and think....how exactly did they design an instruction set and make it work?

edit: I guess for Clarity, pretend im talking about the first microprocessor, how did they go from Binary to actually creating an Instruction Set?

答:
if I understand your question I dont understand how bin/hex or assembly are related.

I assume the meat of your question is how do I get from the basic gates, AND, OR, NOT to instructions like move, load, store, add, etc.

I have my own little teaching instruction set I made from scratch that has some of the details of say how an add and subtract work from basic gates and things like that http://github.com/dwelch67/lsasim.

Look for the Code (something something something) book from Petzold.  May start way to elementary but walks you slowly from nothing to do with computers and electronics into binary, hex, and into the basic gates, etc.

Are you asking about how you would build one from scratch today, or how did they do it back in the day?  Today you would start with a definition of the instruction set.  you just sit down and write it out, you think about the types of instructions you must have the loads and stores and moves and alu stuff, and then how many registers, how big the registers, this in part affects the instruction size, you think about the instruction size...

Let me stop and ask you how do you write a program?  Starting with a blank screen on a text editor?  You have some idea of the task you are trying to solve the variables you might need, the functions, the programming language, etc.  And each person is different but to some extent you do a little of this (say defining and writing functions), a little of that (making header files with reusable defines and enums and structs and stuff), and a little of the other thing (just code, fill the functions with variables and code).  And you circulate around the different tasks, in the end you feel you have a balance of code size, speed, readability, quality, functionality, etc.  No different with hardware design.  hardware designers use programming languages (vhdl, verilog) as well and go through the same process, the programming is only slightly different to software, the primary difference is that different lines/modules of hardware programs execute simultaneously where software executes linearly.

Just like coming up with a software program you balance the desires, performance, size, features, etc.  You might have some design rules forced on you either that you wanted or that your boss made you do, etc.  As with software design well after the initial design into implementation you may find out that you have some big mistakes and have to go back to initial design and change the instruction set, big or small changes.  Might get so far as to have a compiler and simulated processor to find you really needed a couple of specific instructions that dramatically improve the quality of the compiled code, performance, etc.

So you have invented some instruction set from scratch, you have used some experience with hardware design to group similar instructions with similar bit patterns so they can be more easily decoded, not just for hardware language programming but it saves on power and gates and all that good stuff.  These days you would make some sort of a simulator, my understanding is ARM was a software simulator first then the hardware designs came later, dont know if that is true but sticking with that story.  This depends on the team some teams may be just hardware folks and want to just get into programming in the hdl, some like me may want to do a little of both.  These days good hardware language simulators are available so you dont have to build any hardware you compile and simulate and do much of your debugging with a hardware simulation program/package.  the software team can develop assemblers and compilers for the instruction set and using simulated ram and rom feed programs to the simulated processor and put it through its paces.  we have simulated a full linux boot on a processor I worked on not long ago, took many hours but it worked (found a cache bug in the logic that way).

So now for what I really think you were asking.  How do you get from basic gates to a processor with an instruction set.  Well basic gates AND, OR, NOT are really analog, they dont have a concept of time, you cant instantly change the voltage on the inputs and as you change that voltage the outputs start to change.  gates are made of transistors and transistors are amplifiers, take the input multiply it by some number and allow that much current to flow on the other side.  when we use them as logic gates we are actually oversaturating them, the input voltage is so high or low that the transistor can only drive max voltage or no voltage (current).  basically the transitor is turned into a switch.  long story short, there is no concept of time.  In order to have an instruction set we have to have instructions happen in order we have to sequence through the program, we have to have a concept of now we are on this instruction, and in the next time slot we will work on that instruction.  Just like the game of turning an amplifier into a switch you play similar games with using basic logic gates with a clock.  the clocks come from magic crystals in a can (not worth getting into that here) that make voltages that turn on and off at some fixed rate.  use that voltage in logic equations and you can start to sequence things.

very very briefly think of this truth table:

```<code>0 0 0
0 1 1
1 0 1
1 1 0
</code>```

in binary:

```<code>0 + 0 = 1
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10 (2 decimal)
</code>```

focusing on the lsbit only, a one bit adder, the truth table above describes a one bit adder.  It also describes an XOR gate. One input is true or the other but not both.

To get more than one bit you have to look at carry bits carry in and carry out and you need a three bit adder two operands and a carry in with two outputs, carry out and the result bit.  Once you have that three input two output adder you can cascade that as wide as you want.  But this is still analog, the gates change instantly.

How you turn this analog adder into an ADD instruction, is you have some logic that looks at the instruction which is sitting as inputs to these gates you have arranged.  some of the bits in the instruction say, this is an add instruction, some of the bits say that one operand is such and such register, maybe register 7, other bits may say the other operand is register 4.  and depending on the architecture you might have another register defined in the instruction that says put the result in register 2.  Now more logic sees this as I need register 7's contents to be routed to one input of the alu adder and register 4's inputs routed to the adder, and you route the output of the adder to register 2.  Since the clock is part of this logic there is a period of time from the beginning of the clock period to the beginning of the next clock period where all the analog signals settle down and resolve the logic equation they are wired to do. Not unlike when you flip a light switch you change the lights state from say off to on.  it takes a period of time for that light to warm up and basically get into a steady state.  Not much different here.

There is some logic that says things like if this clock period is the execution phase of an AND instruction, then the next clock period I am going to save the result in the output register.  at the same time I am going to fetch the next instruction etc.  So for modern processors where the alu execution is often just one clock period because the analog logic can resolve the logic equations that fast.  Older processors you had to count to some number leave the adder wired up, wait for x number of clock cycles for the adder logic to resolve, then sample the result from the output, feed the alu different inputs, wait x number of clock cycles for that to resolve, repeat forever or until the power goes off.

What do I mean by logic equations?  just that, if you want you can think of it in terms of AND, OR, NOT gates.  For each input bit to the alu adder circuit there is an equation, likely a very long equation which includes the clock, which includes the flip flops (individual/single memory bits) that contain the current instruction (plus the equations that feed each of those memory bits) and on and on.  Take a single software function you have written, in the language you have written it, assuming this is a function that takes the inputs, performs a task and then finishes and returns a result.  Think of all the possible combinations of inputs and what the different execution paths are through that function.  You may have written it in some high level language but you could probably even in that language rewrite it to be more primitive and more primitive using many nested if-then-else structures.  and go lower down into assembly language perhaps.  Not unlike the equations I am talking about, the hardware programmer doesnt program in these long winded equations any more than you probably program in long winded if-then-else trees in assembly language when the programming language of choice saves so much of that.  Just like the compiler you use turns your small source code into long winded assembly with lots of if-then-elses, there is a compiler that takes the hardware programming language code and turns it into a logic equations.  Just like when you take one program written (to be portable) in C and compile it for different instruction sets the assembly and machine code is different, depending on where you plan to build your chip or what programmable chip if you use a cpld or fpga you are using the hardware programmers program resolves to different lists of logic equations based on the logic blocks available from that chip builder or programmable device.

Now going back to the first cpu (which today we would consider a microcontroller but then it was a cpu).  You did all of the above on paper, and you didnt use hardware programming languages you actually wrote the logic equations, but you even more carefully chose the bit patterns for the instructions to make the number of gates and the wires to connect those gates as simple as practical.  On paper, by hand you had to both create the long list of wired up logic gates and then you had to draw the actual components on a blown up version of the silicon mask.  even today chips are done using what is similar to a photographic or silkscreen like process in laymans terms so you would take these blue prints if you will and shrink them then apply them to the silicon layers.

here again back in the day everyone had a better handle on assembly and not only might you end up doing some assembly programming you might not have had a text editor nor an assembler you might have had to write your first programs by hand on paper, then using a reference manual, by hand converted that to machine code, ones and zeros.  On some of those computers you might have had to load the ram by flipping switches, flip the address bits, flip the data bits until they match the numbers on your paper, flip the clock bit up then down and you have loaded one memory location with one byte of one instruction of your program, repeat a few hundred times more and hope you make no mistakes.

In the same way that the first lets say C compiler was probably written in some other language then it became self hosting by being re-written in C and compiled by the first C compiler then again by itself.  Then the C compilers were used to invent other programming languages which then became self-hosting.  We invented operating systems and text editors that built upon themselves, and it is all black magic left for a few folks behind the curtain in the corner to do...

yes, very long winded, it is a big question needing years worth of study and experience to truly grasp.  look at my lsasim, I dont claim to be an expert in anything, but it is an instruction set, there is both a simulator that executes the instruction written in C, and another implementation of the processor implemented in a hardware programming language that can be simulated using different tools.  Plus a crude assembler and some other tools and such.  Perhaps, by examining some of this, in particular the hardware programming language code it might close the gap on what I assume you were asking.  If I have not closed that gap or have made a long winded tangent please let me know i will happly remove this answer (assuming I am able to I dont hang out at programmers exchange much).

Body:
if I understand your question I dont understand how bin/hex or assembly are related.

I assume the meat of your question is how do I get from the basic gates, AND, OR, NOT to instructions like move, load, store, add, etc.

I have my own little teaching instruction set I made from scratch that has some of the details of say how an add and subtract work from basic gates and things like that http://github.com/dwelch67/lsasim.

Look for the Code (something something something) book from Petzold.  May start way to elementary but walks you slowly from nothing to do with computers and electronics into binary, hex, and into the basic gates, etc.

Are you asking about how you would build one from scratch today, or how did they do it back in the day?  Today you would start with a definition of the instruction set.  you just sit down and write it out, you think about the types of instructions you must have the loads and stores and moves and alu stuff, and then how many registers, how big the registers, this in part affects the instruction size, you think about the instruction size...

Let me stop and ask you how do you write a program?  Starting with a blank screen on a text editor?  You have some idea of the task you are trying to solve the variables you might need, the functions, the programming language, etc.  And each person is different but to some extent you do a little of this (say defining and writing functions), a little of that (making header files with reusable defines and enums and structs and stuff), and a little of the other thing (just code, fill the functions with variables and code).  And you circulate around the different tasks, in the end you feel you have a balance of code size, speed, readability, quality, functionality, etc.  No different with hardware design.  hardware designers use programming languages (vhdl, verilog) as well and go through the same process, the programming is only slightly different to software, the primary difference is that different lines/modules of hardware programs execute simultaneously where software executes linearly.

Just like coming up with a software program you balance the desires, performance, size, features, etc.  You might have some design rules forced on you either that you wanted or that your boss made you do, etc.  As with software design well after the initial design into implementation you may find out that you have some big mistakes and have to go back to initial design and change the instruction set, big or small changes.  Might get so far as to have a compiler and simulated processor to find you really needed a couple of specific instructions that dramatically improve the quality of the compiled code, performance, etc.

So you have invented some instruction set from scratch, you have used some experience with hardware design to group similar instructions with similar bit patterns so they can be more easily decoded, not just for hardware language programming but it saves on power and gates and all that good stuff.  These days you would make some sort of a simulator, my understanding is ARM was a software simulator first then the hardware designs came later, dont know if that is true but sticking with that story.  This depends on the team some teams may be just hardware folks and want to just get into programming in the hdl, some like me may want to do a little of both.  These days good hardware language simulators are available so you dont have to build any hardware you compile and simulate and do much of your debugging with a hardware simulation program/package.  the software team can develop assemblers and compilers for the instruction set and using simulated ram and rom feed programs to the simulated processor and put it through its paces.  we have simulated a full linux boot on a processor I worked on not long ago, took many hours but it worked (found a cache bug in the logic that way).

So now for what I really think you were asking.  How do you get from basic gates to a processor with an instruction set.  Well basic gates AND, OR, NOT are really analog, they dont have a concept of time, you cant instantly change the voltage on the inputs and as you change that voltage the outputs start to change.  gates are made of transistors and transistors are amplifiers, take the input multiply it by some number and allow that much current to flow on the other side.  when we use them as logic gates we are actually oversaturating them, the input voltage is so high or low that the transistor can only drive max voltage or no voltage (current).  basically the transitor is turned into a switch.  long story short, there is no concept of time.  In order to have an instruction set we have to have instructions happen in order we have to sequence through the program, we have to have a concept of now we are on this instruction, and in the next time slot we will work on that instruction.  Just like the game of turning an amplifier into a switch you play similar games with using basic logic gates with a clock.  the clocks come from magic crystals in a can (not worth getting into that here) that make voltages that turn on and off at some fixed rate.  use that voltage in logic equations and you can start to sequence things.

very very briefly think of this truth table:

0 0 0
0 1 1
1 0 1
1 1 0

in binary:

0 + 0 = 1
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10 (2 decimal)

focusing on the lsbit only, a one bit adder, the truth table above describes a one bit adder.  It also describes an XOR gate. One input is true or the other but not both.

To get more than one bit you have to look at carry bits carry in and carry out and you need a three bit adder two operands and a carry in with two outputs, carry out and the result bit.  Once you have that three input two output adder you can cascade that as wide as you want.  But this is still analog, the gates change instantly.

How you turn this analog adder into an ADD instruction, is you have some logic that looks at the instruction which is sitting as inputs to these gates you have arranged.  some of the bits in the instruction say, this is an add instruction, some of the bits say that one operand is such and such register, maybe register 7, other bits may say the other operand is register 4.  and depending on the architecture you might have another register defined in the instruction that says put the result in register 2.  Now more logic sees this as I need register 7's contents to be routed to one input of the alu adder and register 4's inputs routed to the adder, and you route the output of the adder to register 2.  Since the clock is part of this logic there is a period of time from the beginning of the clock period to the beginning of the next clock period where all the analog signals settle down and resolve the logic equation they are wired to do. Not unlike when you flip a light switch you change the lights state from say off to on.  it takes a period of time for that light to warm up and basically get into a steady state.  Not much different here.

There is some logic that says things like if this clock period is the execution phase of an AND instruction, then the next clock period I am going to save the result in the output register.  at the same time I am going to fetch the next instruction etc.  So for modern processors where the alu execution is often just one clock period because the analog logic can resolve the logic equations that fast.  Older processors you had to count to some number leave the adder wired up, wait for x number of clock cycles for the adder logic to resolve, then sample the result from the output, feed the alu different inputs, wait x number of clock cycles for that to resolve, repeat forever or until the power goes off.

What do I mean by logic equations?  just that, if you want you can think of it in terms of AND, OR, NOT gates.  For each input bit to the alu adder circuit there is an equation, likely a very long equation which includes the clock, which includes the flip flops (individual/single memory bits) that contain the current instruction (plus the equations that feed each of those memory bits) and on and on.  Take a single software function you have written, in the language you have written it, assuming this is a function that takes the inputs, performs a task and then finishes and returns a result.  Think of all the possible combinations of inputs and what the different execution paths are through that function.  You may have written it in some high level language but you could probably even in that language rewrite it to be more primitive and more primitive using many nested if-then-else structures.  and go lower down into assembly language perhaps.  Not unlike the equations I am talking about, the hardware programmer doesnt program in these long winded equations any more than you probably program in long winded if-then-else trees in assembly language when the programming language of choice saves so much of that.  Just like the compiler you use turns your small source code into long winded assembly with lots of if-then-elses, there is a compiler that takes the hardware programming language code and turns it into a logic equations.  Just like when you take one program written (to be portable) in C and compile it for different instruction sets the assembly and machine code is different, depending on where you plan to build your chip or what programmable chip if you use a cpld or fpga you are using the hardware programmers program resolves to different lists of logic equations based on the logic blocks available from that chip builder or programmable device.

Now going back to the first cpu (which today we would consider a microcontroller but then it was a cpu).  You did all of the above on paper, and you didnt use hardware programming languages you actually wrote the logic equations, but you even more carefully chose the bit patterns for the instructions to make the number of gates and the wires to connect those gates as simple as practical.  On paper, by hand you had to both create the long list of wired up logic gates and then you had to draw the actual components on a blown up version of the silicon mask.  even today chips are done using what is similar to a photographic or silkscreen like process in laymans terms so you would take these blue prints if you will and shrink them then apply them to the silicon layers.

here again back in the day everyone had a better handle on assembly and not only might you end up doing some assembly programming you might not have had a text editor nor an assembler you might have had to write your first programs by hand on paper, then using a reference manual, by hand converted that to machine code, ones and zeros.  On some of those computers you might have had to load the ram by flipping switches, flip the address bits, flip the data bits until they match the numbers on your paper, flip the clock bit up then down and you have loaded one memory location with one byte of one instruction of your program, repeat a few hundred times more and hope you make no mistakes.

In the same way that the first lets say C compiler was probably written in some other language then it became self hosting by being re-written in C and compiled by the first C compiler then again by itself.  Then the C compilers were used to invent other programming languages which then became self-hosting.  We invented operating systems and text editors that built upon themselves, and it is all black magic left for a few folks behind the curtain in the corner to do...

yes, very long winded, it is a big question needing years worth of study and experience to truly grasp.  look at my lsasim, I dont claim to be an expert in anything, but it is an instruction set, there is both a simulator that executes the instruction written in C, and another implementation of the processor implemented in a hardware programming language that can be simulated using different tools.  Plus a crude assembler and some other tools and such.  Perhaps, by examining some of this, in particular the hardware programming language code it might close the gap on what I assume you were asking.  If I have not closed that gap or have made a long winded tangent please let me know i will happly remove this answer (assuming I am able to I dont hang out at programmers exchange much).


答:
At it's core, a CPU is usually just a state machine.  So you'll need to understand how logic gates and flip-flops or registers combine to making state machines.

A state machine takes inputs and the current state, runs them through boolean (and potentially arithmetic) logic, and then provides outputs and a next state.  One of the inputs can be the instruction register.  One of the outputs can be an enable and a selection for the source to reload the instruction register, maybe also increment or load another register acting as a program counter.  With that, plus some addressable memory, you can sequence through instructions.

Once you have a way to sequence instructions, you can use logic to decode these instruction bits, plus the current state, into another bunch of control bits.  Some of these control bits can act as inputs to control a bunch of logic that can do arithmetic and word-wide logic, call it an ALU.  Other bits can load stuff up or select inputs for the ALU.  Other bits can say where to store the results of the ALU.  Or load addressing registers.  Or write to memory or other outputs.  Etc.

Part of designing an instruction set is just figuring out which combinations of bits, when decoded, control all the registers and state machine sequencing.  This had been done and (re)optimized thousands of different ways.

There are at least 3 levels of university textbooks on this non-trivial subject.

Title: How exactly do we go from Binary/Hex to Assembly Instruction sets?

Body:
So i've been trying to learn some Embedded/Assembly programming for a bit here lately, as well as going far as trying to learn the lowest level (gates and such).

One thing puzzles me though....is how do we "get" instruction sets. I understand somewhat how gates/TTL and such works, but I don't see how we get from that to mov,add,clr etc...?

It's probably a stupid question....but I mean I think back to the first micro-processors/controllers and think....how exactly did they design an instruction set and make it work?

edit: I guess for Clarity, pretend im talking about the first microprocessor, how did they go from Binary to actually creating an Instruction Set?


问:
When to Stop Debug
I've read the article about fixing bug in this post What process do you normally use when attempting to debug a problem/issue/bug with your software?. One of the answer which I noted is "take a rest" when you have spent too long to try to fix the bug. I believe it is a good idea too.

But sometime I am in a tight deadline when some mysterious bug appears. When this is happened I tend to think to rewrite the code rather than spending more time to fix the bug.

My question is, when will you think it is better to rewrite the code rather than fix it? Or what criteria can we use to determine whether to keep fix the bug or rewrite the code?

答:
A proper preparation before delving directly into code would never need you to rewrite it.
If you are rewriting your code often it means that the method you have chosen is lacking proper analysis of requirement and/or technology and/or approach. Do not underestimate the art of Software Engineering. It saves lot of time and brain damage.

Keep commenting, versioning could also save you some rework.

As for when you can rewrite the code than to debug. Do it only if

Piece of code is small enough.

You know that it would not solve the problem

You are working on someone else's uncommented code (it again has to be small)

You have lot of time and are getting shivers just by looking at the existing code. :)

Title: When to Stop Debug


问:
What is the best way to evaluate new programmers?
What is the best way to evaluate the best candidates to get a new job (talking merely in terms of programming skills)?  In my company we have had a lot of bad experiences with people who have good grades but do not have real programming skills.  Their skills are merely like code monkeys, without the ability to analyze the problems and find solutions.

More things that I have to note:

The education system in my country sucks--really sucks.  The
people that are good in this kind of job are good because they have talent for it
or really try to learn on their own.

The university / graduate /post-grad degree doesn't mean necessarily that you know exactly how to do the things.

Certifications also mean nothing here because the people in charge of the certification course also don't have skills (or are in low paying jobs).

We need really to get the good candidates that are flexible and don't have mechanical thinking (because this type of people by experience have a low performance).

We are in a government institution and the people that are candidates don't necessarily come from outside, but we have the possibility to accept or not any candidates until we find the correct one.

答:
Ask them about the most interesting programming challenge that they have ever tried to solve but could not, what approach did they use while solving it, why they could not solve and what other approach they think can solve it.

This is enough for me to judge a programmers abilities as a programmer.


答:
If you are on a tight deadline and decide to rewrite the code, how do you know you wouldn't introduce more bugs than what you are trying to fix? And after you go through the rewrite, for all you know, the same bug might still be there.  What if the root cause of the problem happens to be your understanding of some external API?  Your code might be new, but your understanding of interacting with other components is the same.

I would advise to NEVER rewrite any code just because it has a bug that you don't understand. As software engineers, significant portion of our jobs is debugging. And there should be no reason why a bug can't be found. Keep digging and unwrapping layers. Seek out help of tools such as logging (homegrown or frameworks), debuggers and so on.  These are the types of experiences that make you a better developer. Not only you will gain skills which you are currently missing, but you will also gain insight into what not to do in the future. If all else fails, you start the painstaking process of manual binary search (disable half the code and see how that affects the bug, then keep doing the subdivision until you narrow it down enough)

If you need to take a break, take it. Another thing that helps is to sit down with a coworker and explain to him what you've found and your steps.  a) your co-worker might have additional advice and b) you use him as a sounding board and sometimes when you speak out loud, you might realize what you've been overlooking yourself.

Title: When to Stop Debug

Body:
I've read the article about fixing bug in this post What process do you normally use when attempting to debug a problem/issue/bug with your software?. One of the answer which I noted is "take a rest" when you have spent too long to try to fix the bug. I believe it is a good idea too.

But sometime I am in a tight deadline when some mysterious bug appears. When this is happened I tend to think to rewrite the code rather than spending more time to fix the bug.

My question is, when will you think it is better to rewrite the code rather than fix it? Or what criteria can we use to determine whether to keep fix the bug or rewrite the code?


答:
Changing the code in any way imposes a risk of introducing new bugs into the code. The bigger the changes, the bigger the risk. You can mitigate that risk via unit (and integration/system/...) testing (but can't ever eliminate it completely).

Obviously, a total rewrite has a significantly higher risk than just fixing a specific bug. In order to create a proper fix, you have to understand the problem and the solution well enough so that fixing one issue doesn't break some other use case. But so is the case for a rewrite. If you don't understand what's going on during debugging, obviously the code in question is complex, so rewriting it is going to be far from trivial, and usually takes way more time you would assume. Which, under a tight deadline, is not good news...

Moreover, being tired and under pressure always increases the risk of making bad decisions and mistakes, thus causing more bugs.

So I personally would strongly prefer debugging and fixing the concrete bug rather than rewriting, except when the code in question is really really terrible and I have a clear specification (in the form of documents and/or unit tests) of what it is supposed to do and I have enough time to do it properly.

(Note also that if the code is really so terrible, it is exceedingly rare that it is properly documented and/or unit tested. In this case, one needs even more time to first construct a proper unit test suite to "record" the behaviour of the current code, to be able to verify that the new implementation reproduces it faithfully in every aspect except the bug fix.)

If you are stuck with your current approach, it is indeed a good idea to take a rest and do something else to relax your brain and allow your subconscious to work on the problem in peace. It is also useful to ask help from a colleague (or StackOverflow). See this earlier related thread for more details:

Dealing with frustration when things don't work

Title: When to Stop Debug


答:
If you development process focuses on producing carefully crafted code (including design, unit testing, documentation, version control, traceability...), TDD should not cost much more time.

Moreover, TDD allows huge time gains in maintenance, especialy when customer asks for a new feature that needs a big refactoring.

Quoting Thorbjørn Ravn Andersen:

TDD is an investment in maintenance cost, not initial development.

Title: Emphasizing the importance of TDD to customers

Body:
The importance of TDD needs to be propagated but there's always a gap in the project timeline and time needed for developing a TDD project.  Customers usually do not understand the importance of code maintenance or TDD and want the project to be finished as soon as possible.

The result would be a Test After Development which would be very basic minimal tests to please the coverage tools and let the project analyzers have a great Graph.

Do projects developed using TDD take longer, or is that just an unfounded fear?


问:
Are null references really a bad thing?
I've heard it said that the inclusion of null references in programming languages is the "billion dollar mistake".  But why?  Sure, they can cause NullReferenceExceptions, but so what?  Any element of the language can be a source of errors if used improperly.

And what's the alternative?  I suppose instead of saying this:

Customer c = Customer.GetByLastName("Goodman"); // returns null if not found
if (c != null)
{
    Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!");
}
else { Console.WriteLine("There was no customer named Goodman.  How lame!"); }
```

<p>You could say this:</p>

<pre class="lang-cs prettyprint-override"><code>if (Customer.ExistsWithLastName("Goodman"))
{
    Customer c = Customer.GetByLastName("Goodman") // throws error if not found
    Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!");
}
else { Console.WriteLine("There was no customer named Goodman.  How lame!"); }
</code>```

But how is that better?  Either way, if you forget to check that the customer exists, you get an exception.

I suppose that a CustomerNotFoundException is a bit easier to debug than a NullReferenceException by virtue of being more descriptive.  Is that all there is to it?

答:
Optimise for the most common case.

Having to check for null all the time is tedious - you want to be able to just get hold of the Customer object and work with it.

In the normal case, this should work just fine - you do the look up, get the object and use it.

In the exceptional case, where you're (randomly) looking up a customer by name, not knowing whether that record/object exists, you'd need some indication that this failed. In this situation, the answer is to throw a RecordNotFound exception (or let the SQL provider beneath do this for you).

If you're in a situation where you don't know whether you can trust the data coming in (the parameter), perhaps because it was entered by a user, then you could also provide the 'TryGetCustomer(name, out customer)' pattern. Cross-reference with int.Parse and int.TryParse.

Title: Are null references really a bad thing?


答:
You don't need to avoid your current situation to feel better. Just name it: Refactoring.

The process of introducing new feature A that needs changes in existing feature B is:

change B so that it still works as expected and allows future A to be inserted

insert A with updated B

test B

test A

As you see, you need to have a good regression test suite.

Title: Evidence of Bad Design: Updating feature A breaks/interferes with existing feature B

Body:
I am working on a Javascript Web App & I am finding as I expand the program & add new features(new animations) it causes existing features to break or work differently than prior to adding that new feature. So as I continue to finish the app, it keeps breaking old features & I have to go back & redo/update those features. So it seems I never complete a feature because I am always coming back to it so I can get it to work nicely with other features.

Is this indicative of bad application design? Or is this a normal feature of computer programming, ie just like how in any program you will spend 20% of time developing the program & 80% of the time fixing bugs(or is it maintaining the program?)?

Are there design &/or any other techniques I can employ to avoid having this problem occur?

The application is a renderer (which takes an XML file which contains information about objects that perform animations - move around, fade etc.) that creates HTML elements & animates them.

The design is OOP, with as close as you can get to classes in Javascript by using prototype. It employs ALOT of multiple inheritence. It also makes use of the anonymous functions where possible so I think it would be very much like a Java project because they both have OOP, anon functions & inheritence. There is a class purely dedicated towards animation called AnimatedObject & many objects inherit from this class. You just perform an animation by simply calling a function from that class such as myAnimObj.performFade() or myAnimObj.performRotate().


问:
Should unit tests be stored in the repository?
I'm a growing programmer who's finally putting unit testing into practice for a library that I'm storing on GitHub.

It occurred to me that I might include the test suites in the repo, but as I look around at other projects, the inclusion of tests seems hit-or-miss.

Is this considered bad form? Is the idea that users are only interested in the working code and that they'll test in their own framework anyway?

答:
You definitely should put your tests into the repository. Tests are in my opinion part of the code and can help others immensely to understand it (if well written). Besides, they can help others when changing or contributing to your codebase. Good tests can give you the confidence that your changes do not inadvertently break anything.

The test code should be well separated from production code, though. Maven for example achieves this by putting production and test code into different folders. The question "is this file part of production or of the test code" should never arise.

I personally do not write unit tests for used libraries in my own code. I expect them to be working (at least when I use a release version, though bugs obviously can appear). It gets some test coverage in integration tests, but that's not enough.


答:
If you don't include the unit tests in the checked-in source code, then:

how is someone who downloads and builds their own copy of that code going to verify that it's working the way it was intended? Compiler and library bugs are rare, and data errors (particularly ones that don't render the source code impossible to compile) are even more rare, but they definitely can crop in, particularly when you cannot dictate the build environment to the degree that an employer can dictate which tools are used.

how are you going to get the tests back if something happens to your local copy of the source code?

how is a new developer going to verify that their changes doesn't break anything in the existing code base?

Bottom line, I would consider not including any unit tests written in the official source code repository a very bad thing.

Title: Should unit tests be stored in the repository?

Body:
I'm a growing programmer who's finally putting unit testing into practice for a library that I'm storing on GitHub.

It occurred to me that I might include the test suites in the repo, but as I look around at other projects, the inclusion of tests seems hit-or-miss.

Is this considered bad form? Is the idea that users are only interested in the working code and that they'll test in their own framework anyway?


答:
Of course you should put unit tests into the repository, for several reasons:

it is easy to revert to previous version

other people working on the project also gain access to unit tests

some people consider unit tests as part of the documentation (TDD and BDD)


答:
If there is any chance to run them on another computer, definitely include them. They should be built separately, so users don't have to, and they may have extra dependencies, but they should be definitely included.

I'd strongly suspect most projects that don't include tests in the repository simply don't have any.

There may be a reason to have the tests as separate module, so you can easily run new tests against older code. It would be useful for API-stable library or black-box tests via command-line; usefulness for compiled languages where the new tests probably won't compile with older code is limited.


答:
My question is, when will you think it is better to rewrite the code
  rather than fix it?

I'm tempted to say "never". The problem is: Rewriting may seem easier, but experience tells that usually new code will have new bugs. So you'll probably replace one bug with several new ones.

Furthermore, if you don't understand why the bug occurs, what tells you that your rewrite will not accidentally contain the same bug (maybe it was a design error, or a misunderstanding on your part).

There may be situations where code is so buggy that it's just not worth salvaging, but these are very rare. I have only had it happen once or twice in almost ten years of development work.

This really only applies to code that is so buggy that it practically does not work at all.
As long as the code mostly works, I would never rewrite it, no matter how ugly or complicated it is.

Title: When to Stop Debug


问:
How do you keep track of large projects?
When dealing with a project that has many different files, I always seem to loose track of how the parts interact with one another. I've never really had much of a problem understanding smaller components in isolation, but as the complexity of the project increases, I find myself unable to mentally construct an understanding of what is going on. I notice this especially with OOP projects, as the number of methods and source files increase.

My background:
I'm a self-taught web programmer. I've dealt mostly with python for quick and dirty scripts, but I've also done a few basic django projects. I like web frameworks such as flask, because in the simplicity of a single-file layout, I can easily keep track (mostly) of what is going on.

I now find myself in a situation where I need to interact with a large Zend Framework PHP project that someone else developed, and I'm overwhelmed with trying to understand the code spread out to numerous files.

What techniques and processes have you found useful to understand a large code base that someone else has developed? Is there any particular diagram that you find helps you grasp the larger picture?

答:
What I do is to create a single UML model from all files which had been reversed from java to UML. This approach means that the model is not anymore just an abstract view of the project but the project itself entirely mapped to MOF and therefore UML.

What I get is a large single model composed by multiple sub models each composed by packages which are composed by classifiers etc.... Working at multi project level also allows me to trace each classifiers and method calls at multiproject levels. I mean that the same method can call one classifier in the project A and another classifier in the project B. The only way to see the full structure of the project is to reverse both of them at the same time. I don't have time to create component diagrams and the information is not really accurate. I prefer to ask the computer to reverse the full project for me. I do a reverse at each iteration with the team and all my diagrams are immediately updated. The reverse engineering is incremental and use the Java to UML Ids mapping. I mean that each java element is mapped to a single and unique MOF element which remain the same during all the project life even if refactored. Doing that gives no more limit to UML modeling and allows very very large and complex project modeling. For your information I work with project having more than 5 000 000 lines of OOP code. All my projects are reversed properly and graphical navigation is possible

I only use class diagrams because from my UML model I can create as many views as needed which are always up to date. I can also model very complex projects.


答:
Having worked with Smalltalk myself for two years, I can tell you I haven't seen any Python IDE available that will give you the level of expressiveness you are looking for in Smalltalk IDEs such as VisualWorks or Squeak.

The key thing about most Smalltalk IDEs is that code + development tools are stored in the same place. So rather than coding in a text editor, then compiling/interpreting it on a VM, It's all done on the same binary. This has obvious benefits as you could connect to a Smalltalk image in a production environment and start coding/debugging on the image itself rather than having to change then publish a new copy as everything is already there.  The main drawback I found with this approach is the amount of memory it consumes. You can obviously strip the image down to remedy this, but that takes time.

I will say that it's not impossible to have a Python IDE that does this, but there simply isn't one available as far as I've seen. Despite the dynamic nature of both languages, the approach to development between both languages different given that Python is file based and Smalltalk is image based.

Title: Is there an IDE for python that creates the same kind of reflective environment that Smalltalk provides?

Body:
As anyone who has used Smalltalk knows, one of the main benefits (other than a late-bound language that discourages many poor practices), is that the system is totally transparent and reflective, which makes understanding APIs and existing code easy, and locating functionality pretty easy.

Is there anything that creates a similar environment for Python?

A few examples of features of a smalltalk development environment, not natively found in python are:

search class/method/etc names,

examine inheritance hierarchies

functionality to show the full interface of a given class/object, and where the properties therein originate

an integrated graphical debugger which allows one to examine the full state of everything in the system, and see every instance of a given type, as well as all threads.

Note that I use windows, so anything that works well on windows would be particularly useful.


答:
spend 20% of time developing the program & 80% of the time fixing bugs

No, definitely this is not normal: it's a sign the project has reached and (far) passed the point of reasonable maintainability. I'd consider even 50/50 to be a bad sign.

Formally speaking, if by modifying feature A you break feature B, it means you don't understand the code. If you did understand it, you wouldn't leave undesired side effects by making changes in it.

However, who's to take the blame for this? Is it the code that's too messy, complex to be understood in its entirety, or is it you unwilling or unable to understand the code? That's an important question to be answered before you either sit down and study the code or persuade your management the code requires a fundamental rewrite.

In general, number one contributor to complexity of the code (not functionality) is too many static variables or class fields. A program or an object has a finite number of states, which comprises of all possible combinations of values in variables. With each new variable  you get an exponential growth of the number of possible states, i.e. you get a growth of complexity and incomprehensibility for a human mind.

Good design minimizes the number of possible static states and isolates components as much as possible. Look at the code from this point of view, and see if you can understand and memorize the meaning of each static var/member field and each function. If you can't recall something the following day, I'd say go for refactoring.


问:
Suggested HTTP REST status code for 'request limit reached'
I'm putting together a spec for a REST service, part of which will incorporate the ability to throttle users service-wide and on groups of, or on individual, resources.  Equally, time-outs for these would be configurable per resource/group/service.

I'm just looking through the HTTP 1.1 spec and trying to decide how I will communicate to a client that a request will not be fulfilled because they've reached their limit.

Initially I figured that client code 403 - Forbidden was the one, but this, from the spec:

Authorization will not help and the request SHOULD NOT be repeated

bothered me.

It actually appears that 503 - Service Unavailable is a better one to use - since it allows for the communication of a retry time through the use of the Retry-After header.

It's possible that in the future I might look to support 'purchasing' more requests via eCommerce (in which case it would be nice if client code 402 - Payment Required had been finalized!) - but I figure that this could equally be squeezed into a 503 response too.

Which do you think I should use?  Or is there another I've not considered?

答:
To an extent, you're free to do what you like with the codes, but I would agree that you can use 503, or if you want 402, without anyone being able to complain that you are breaking things.

Edit: A purist might say that you should start with 503, then switch once it's possible to make payments.

An excellent addition to this in the comments:

A 4xx indicates an error by the client that can be fixed by them taking a certain action, whereas a 5xx indicates a problem on the server that the client can't help resolve. So in your case, a 4xx is more appropriate, because the (i) the server is behaving exactly as it should, and (ii) the client can "fix" the error by either slowing down or purchasing more credits. The exact resolution can be indicated in the body of the 429 response. – Mike Chamberlain 7 hours ago


问:
Git & project backups
I've been using SVN for sometime and have been making an awkward, but soon to be rewarding transition over to git.

Theres quite a few side / small projects that I'm working on which 90% will never see the light of day. As well - I also have my weekly school assignments / projects, and finally client projects that I have on the go.

I've been rolling the idea or question of how or what the best way would be to back up my projects.

The solutions I've sought out so far:

github which offers an outstanding service - I'm ok with my work being open source, however It's the school work and client work I might not want the public to be open to. github, of course has a payment plan - but let's face it, im a poor colleage student doing what I can to at least put KD on the table!

Theres the USB thumbstick that I can take around with me, work off of or back up, but that requires it to be around constently.

Theres Dropbox, but thats a little overkill since it already is a form of a version control system, as well - I have quite a few things on the go - putting everything within dropbox would eat a lot of space

Finally, theres a private server. I have a mac mini setup as a media server and I was thinking that I could backup to that.

Anyways - what are your guys thoughts, how do you handle backing up projects, not only for version control but for the everyday backups.

答:
This wasn't the case at the time when this question was asked, but now Bitbucket also supports Git repositories (in addition to Mercurial).

For free, you get an unlimited number of public and private repositories. The only limitation is that no more than five users can access your private repositories. There are other plans that cost actual money and allow more users, but for you the free plan should be sufficient.

Concerning backups:

I have my own stuff on Bitbucket as well, and I backup everything to my local machine frequently (and to USB disks from there).

I didn't find a tool for automatically pulling all my repositories from Bitbucket, so I wrote my own:

Bitbucket Backup (free & open source, but Windows only).

Title: Git & project backups