答:
Nothing needs to change.

As pointed out by Thomas, software engineering is already a profession.  It can be called engineering, programming, hacking, and/or crafting, but it is as profession and lots of people are making money on it.

I think your question is is around licensing.

Right now there is no formal licensing for software engineering.  Anyone with enough smarts and programming ability can get hired and paid for creating code than runs on a machine or a device.

This is unlike other industries (law and medicine being examples as cited in the question).  A license is required for those professions.  Anyone can drive a car, but to drive one legally you have to have a dirvers license is another example.  Anyone can program, no license or certification(s) required.

Now, I beleive that licensing is good in that it proves that someone has the ability to do something (like drive a car) and knows the ins and outs of the rules (of the road).

A similiar license could be required for software engineering, but I don't think it would do much good.  In fact there are many licensed drivers who are horrible drivers, so just becase you have a license doesn't mean your a good driver or programmer.

A license creates a barrier for entry, which in this industry would not be a good thing, so I don't see any perceived benefit of such licensing.

Companies that hire software engineers should definately test the ability of that potential programmer with a "programming test" (and I am no talking about fizz buzz type) based on the skill set needed.  Programmers with "certifications" look good on paper, but they should really be put to the test with a real world test to gauge experience and aptitude.


问:
What should I do when waiting for a review?
Before asking my question, I must explain the situation.

I'm working for a company as a junior software engineer. One of the seniors always stops me when I have finished my development and want to commit.

He always wants me to wait for him to review it. This is ok, because usually he finds some bugs, and does some optimizations.

However I must commit my code before the deadline. When I finished, I call him and say it is finished. He usually comes late. So my code is late too.

My question is, what should I do? Should I wait him for a review?

EDIT: Addition to the question. I'm curious about one more issue.

I want to be free when coding. How could I gain the trust for freedom of development?

Some explanations:
I've talked with him about this. But it didn't help. We use an issue tracker already, but there isn't any task for reviews. There are just development and test tasks.

答:
Use git locally, commit your changes to a branch and start on task 2 while you wait.  Then when he gets done, you can merge his changes into your new work and you are already ahead of the curve on the next task.

Do this long enough and pretty soon, he can review 2 or more things at one sitting.  Pick things where the lines are unlikely to overlap to minimize conflicts.

ContentLicense: CC BY-SA 3.0


问:
How does a programmer used to static languages cope with lack of Javascript tooling
I have programmed pretty much exclusively in compiled languages, particularly Java, for most of my career.  One of my favourite things about Java is how productive you can be, and how little code you actually have to write, when using tools like Eclipse.

You can:

Easily and automatically refactor your methods and classes

View instantly all the places where a method is invoked, or a constant is used (Open Call Hierarchy/Show References)

Static typing means you can use code completion to show all the parameters/functions available on an object

Control-click on a function/member/class name to go straight to its definition

All these facilities make me feel like the IDE is my best friend.  Writing Java code and particularly understanding other peoples' programs becomes far easier.

However, I am being called on more and more to use Javascript, and my experience so far has been quite negative.

In particular:

No immediate way of finding a function's entry point
(other than a plain text search, which may then result in a subsequent searches for methods further up the call hierarchy, after two or three of which you've forgotten where you started)

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter
(other than actually running the program, navigating to the point at which the function is called, and using console.logs to output all the properties available)

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

The upshot is that you pretty much need to have the entire program in your head at all times.  This massively increases the cognitive load for writing complex programs.  And all this extra stuff to worry about leaves less room in my brain for actual creativity and problem solving.

Sure, it's faster to just throw an object together rather than write an entire formal class definition.  But while programs may be slightly easier and quicker to write, in my experience they are far harder to read and debug.

My question is, how do other programmers cope with these issues?  Javascript is clearly growing in popularity, and the blogs I read are about how productive people are being with it, rather than desperately trying to find solutions to these issues.

GWT allows you to write code for a Javascript environment in Java instead, but doesn't seem to be as widely used as I would expect; people actually seem to prefer Javascript for complex programs.

What am I missing?

答:
I'd like to add an answer to this question as I've been trudging through some good, bad but mostly ugly Java lately and I have a whole new whopper-load of gross over-generalizations about Java and Java devs vs. JS and JS devs that might actually be based in something vaguely resembling useful truth.

There Are IDEs But It Can Be Helpful to Understand Why There Haven't Been Many

I've been trying Webstorm out now that I find myself drawn to Node development and it's not-bad-enough that I actually bought it but I still tend to open js files in Scite more often than WS. The reason for this is that you can do a lot more with a lot less in JS but also because UI work gives immediate feedback, browser dev tools (Chrome's and Firebug in particular) are actually quite excellent, and (accounting for non-browser contexts) re-running altered code is fast and easy without a compile step.

Another thing I'm fairly convinced of is that IDEs basically create their own demand by enabling sloppy code which you really can't afford in JavaScript. Want to learn how we manage in JS? It might help to start by trying to write something non-trivial in Java without an IDE and pay close attention to the things that you have to start doing and think about in order to actually be able to maintain/modify that code without an IDE moving forward. IMO, those same things are still critical to writing maintainable code whether you have an IDE or not. If I had to write a 4-year programming curriculum, it wouldn't let you touch an IDE for the first two years in the interest of not getting tools and dependencies twisted.

Structure

Experienced JS devs dealing with complex applications can and do structure their code. In fact it's one thing we tend to have to be better at with an early history that lacked IDEs to read the code for us but also because powerfully expressive languages can powerfully express completely unmaintainable disaster codebases very quickly if you don't code thoughtfully.

I actually had a fairly steep learning curve in understanding our Java codebase recently until I finally realized that none of it was proper OOP. Classes were nothing more than bundles of loosely related methods altering globally available data sitting around in beans or DTOs or static getters/setters. That's basically the same old beast that OOP was supposed to replace. So I stopped looking and thinking about the code basically. I just learned the shortcut keys and traced through the messes and everything went much more smoothly. So if you're not in the habit  already, think a lot harder about OOD.

A well-structured JS app at the highest level will tend to consist of complex functions (e.g. jQuery) and objects interacting with each other. I would argue that the mark of a well-structured, easily maintained app in any language is that it's perfectly legible whether you're looking at it with an IDE or Notepad++. It's one of the main reasons I'm highly critical of dependency injection and test-first TDD taken to the extreme.

And finally, let go of classes. Learn prototypal inheritance. It's actually quite elegant easy to implement when you actually need inheritance. I find compositing approaches tend to work much better in JS, however, and I personally start to get ill and have EXTJS night-terrors any time I see more than one or two levels of inheritance going on in any language.

Core Principles First

I'm talking about the core stuff that all other good practices should derive from: DRY, YAGNI, the principle of least astonishment, clean separation of problem domains, writing to an interface, and writing human legible code are my personal core. Anything a little more complex that advocates the abandonment of those practices should be considered Kool Aid in any language, but especially a language like JavaScript where it's powerfully easy to leave a legacy of very confusing code for the next guy. Loose coupling, for instance, is great stuff until you take it so far that you can't even tell where interaction between objects is happening.

Don't Fear Dynamic Typing

There aren't a lot of core types in JavaScript. For the most part, dynamic casting rules are practical and straight-forward but it pays to learn them so you can better learn to manage data flow without needless casts and pointless validation routines. Trust me. Strict types are great for performance and spotting problems on compile but they don't protect you from anything.

Learn the Crap out of JS Functions and Closures

JS's first-class functions are arguably the main reason JS won the "Only Language Worth Touching the Client-Side Web With Award." And yes, there actually was competition. They're also a central feature of JS. We construct objects with them. Everything is scoped to functions. And they have handy features. We can examine params via the arguments keyword. We can temporarily attach and fire them in the context of being methods of other objects. And they make event-driven approaches to things obscenely easy to implement. In short, they made JS an absolute beast at reducing complexity and adapting varying implementations of JS itself (but mostly the DOM API) right at the source.

Re-Evaluate Patterns/Practices Before Adopting

First class functions and dynamic types render a lot of the more complex design patterns completely pointless and cumbersome in JS. Some of the simpler patterns, however, are incredibly useful and easy to implement given JS's highly flexible nature. Adapters and decorators are particularly useful and I've found singletons helpful for complex ui widget factories that also act as event-managers for the ui elements they build.

Follow the Language's Lead and Do More With Less

I believe one of the Java head honchos makes the argument somewhere that verbosity is actually a positive feature that makes code easier to understand for all parties. Hogwash. If that were true, legalese would be easier to read. Only the writer can make what they've written easier to understand and you can only do that by putting yourself in the other guy's shoes occasionally. So embrace these two rules. 1. Be as direct and clear as possible. 2. Get to the damn point already. The win is that clean, concise code is orders of magnitude easier to understand and maintain than something where you have to traverse twenty-five layers to get from the trigger to the actual desired action. Most patterns that advocate that sort of thing in stricter languages are in fact workarounds for limitations that JavaScript doesn't have.

Everything is Malleable and That's Okay

JS is probably one of the least protectionist languages in popular use. Embrace that. It works fine. For instance you can write objects with inaccessible persistent "private" vars by simply declaring regular vars in a constructor function and I do this frequently. But it's not to protect my code or users of it "from themselves" (they  could just replace it with their own version during run-time anyway). But rather it's to signal intent because the assumption is that the other guy is competent enough to not want to mangle any dependencies and will see that you're not meant to get at it directly perhaps for a good reason.

There Are No Size Limits, Only Problem Domains

The biggest problem I have with all the Java codebases I've seen is an overabundance of class files. First of all SOLID is just a confusing reiteration of what you should already know about OOP. A class should handle a specific set of related problems. Not one problem with one method. That's just taking bad old chaining func-spaghetti C code only with the addition of all the pointless class syntax to boot. There is no size or method limit. If it makes sense to add something to an already long function or class or constructor, it makes sense. Take jQuery. It's an entire library-length toolset in a single function and there is nothing wrong with that. Whether we still need jQuery is up to reasonable debate but in terms of design, you can learn a hell of a lot about how to write effective JavaScript by understanding how JQ is architected for minimal memory usage/performance impact through slick use of closures and the prototype property.

If Java is All You Know, Dabble in Something With a Non-C-Based Syntax

When I started messing with Python because I liked what I was hearing about Django, I learned to start separating syntax from language design. As a result, it became easier to understand Java and C as a sum of their language design parts rather than a sum of things they do differently with the same syntax. A nice side-effect is that the more you understand other languages in terms of design, the better you'll understand the strengths/weaknesses of the one you know best through contrast.

Conclusion

Now, considering all of that, lets hit all your problem-points:

No immediate way of finding a function's entry point (other than a plain text search, which may then result in a subsequent searches for methods further up the call hierarchy, after two or three of which you've forgotten where you started)

Chrome and Firebug do actually have call-tracing. But see also my points on structure and keeping things concise and direct. The more you can think of your app as larger well-encapsulated constructs interacting with each other, the easier it is to figure whose fault it is when things go wrong. I'd say this is true of Java too. We have class-like function constructors that are perfectly serviceable for traditional OOP concerns.

```<code>function ObjectConstructor(){
    //No need for an init method.
    //Just pass in params and do stuff inside for instantiation behavior

    var privateAndPersistent = true;

    //I like to take advantage of function hoisting for a nice concise interface listing
    this.publicAndPointlessEncapsulationMurderingGetterSetter
    = publicAndPointlessEncapsulationMurderingGetterSetter;
    //Seriously though Java/C# folks, stop with the pointless getter/setters already

    function publicAndPointlessEncapsulationMurderingGetterSetter(arg){
        if(arg === undefined){
            return privateAndPersistent;
        }
        privateAndPersistent = arg;
    }

}

ObjectConstructor.staticLikeNonInstanceProperty = true;

var instance = new ObjectConstructor();//Convention is to  capitalize constructors
</code>```

In my code, I almost never use the object literals {} as structural app components since they can't have internal (private) vars and prefer instead to reserve them for use as data structures. That helps set an expectation that maintains clarity of intent. (if you see curlies, it's data, not a component of app architecture).

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter (other than actually running the program, navigating to the point at which the function is called, and using console.logs to output all the properties available)

Again, see modern browser tools. But also, why is it such a bummer to run the program again? Reload is something a client-side web dev typically hits every few minutes because it costs you absolutely nothing to do it. This is again, another point that app structure can be helpful with but it is one down-side tradeoff of JS that you have to run your own validation when enforcing contracts is critical (something I only do at endpoints exposed to other things my codebase doesn't control). IMO, the tradeoff is well worth the benefits.

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

Yeah that's bad on anything non-trivial. Don't do that. Name your functions kids. It's easier to trace things as well. You can define, evaluate (required to assign), and assign a simple trivial function in-line with:

doSomethingWithCallback( (function callBack(){}) );

Now Chrome will have a name for you when you're tracing through calls. For non-trivial func I would define it outside of the call. Also note that anonoymous functions assigned to a variable are still anonymous.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

I never touch the stuff. Crockford's given some good things to the community but JSLint crosses the line into stylistic preferences and suggesting certain elements of JavaScript are bad parts for no particularly good reason, IMO. Definitely ignore that one thing about regEx and negation classes followed by * or +. Wildcards perform more poorly and you can easily limit the repetition with {}. Also, ignore anything he says about function constructors. You can easily wrap them in a factory func if the new keyword bothers you. CSSLint (not Crockford's) is even worse on the bad advice front. Always take people who do a lot of speaking engagements with a grain of salt. Sometimes I swear they're just looking to establish authority or generate new material.

And again, you must unlearn what you have learned with this run-time concern you have. (it's a common one I've seen with a lot of Java/C# devs) If seeing errors in run-time still bothers you 2 years later, I want you to sit down and spam reload in a browser until it sinks in. There is no compile-time/run-time divide (well not a visible one anyway - JS is run on a JIT now). It's not only okay to discover bugs at run-time, it's hugely beneficial to so cheaply and easily spam reload and discover bugs at every stopping point you get to.

And get crackin' on those Chrome dev tools. They're built-in directly to webkit. Right-click in Chrome. Inspect element. Explore the tabs. Plenty of debug power there with the ability to alter code in the console during run-time being one of the most powerful but less obvious options. Great for testing too.

On a related note, errors are your friends. Don't ever write an empty catch statement. In JS we don't hide or bury errors (or at least we shouldn't cough YUI /cough). We attend to them. Anything less will result in debug pain. And if you do write a catch statement to hide potential errors in production at least silently log the error and document how to access the log.

Body:
I'd like to add an answer to this question as I've been trudging through some good, bad but mostly ugly Java lately and I have a whole new whopper-load of gross over-generalizations about Java and Java devs vs. JS and JS devs that might actually be based in something vaguely resembling useful truth.

There Are IDEs But It Can Be Helpful to Understand Why There Haven't Been Many

I've been trying Webstorm out now that I find myself drawn to Node development and it's not-bad-enough that I actually bought it but I still tend to open js files in Scite more often than WS. The reason for this is that you can do a lot more with a lot less in JS but also because UI work gives immediate feedback, browser dev tools (Chrome's and Firebug in particular) are actually quite excellent, and (accounting for non-browser contexts) re-running altered code is fast and easy without a compile step.

Another thing I'm fairly convinced of is that IDEs basically create their own demand by enabling sloppy code which you really can't afford in JavaScript. Want to learn how we manage in JS? It might help to start by trying to write something non-trivial in Java without an IDE and pay close attention to the things that you have to start doing and think about in order to actually be able to maintain/modify that code without an IDE moving forward. IMO, those same things are still critical to writing maintainable code whether you have an IDE or not. If I had to write a 4-year programming curriculum, it wouldn't let you touch an IDE for the first two years in the interest of not getting tools and dependencies twisted.

Structure

Experienced JS devs dealing with complex applications can and do structure their code. In fact it's one thing we tend to have to be better at with an early history that lacked IDEs to read the code for us but also because powerfully expressive languages can powerfully express completely unmaintainable disaster codebases very quickly if you don't code thoughtfully.

I actually had a fairly steep learning curve in understanding our Java codebase recently until I finally realized that none of it was proper OOP. Classes were nothing more than bundles of loosely related methods altering globally available data sitting around in beans or DTOs or static getters/setters. That's basically the same old beast that OOP was supposed to replace. So I stopped looking and thinking about the code basically. I just learned the shortcut keys and traced through the messes and everything went much more smoothly. So if you're not in the habit  already, think a lot harder about OOD.

A well-structured JS app at the highest level will tend to consist of complex functions (e.g. jQuery) and objects interacting with each other. I would argue that the mark of a well-structured, easily maintained app in any language is that it's perfectly legible whether you're looking at it with an IDE or Notepad++. It's one of the main reasons I'm highly critical of dependency injection and test-first TDD taken to the extreme.

And finally, let go of classes. Learn prototypal inheritance. It's actually quite elegant easy to implement when you actually need inheritance. I find compositing approaches tend to work much better in JS, however, and I personally start to get ill and have EXTJS night-terrors any time I see more than one or two levels of inheritance going on in any language.

Core Principles First

I'm talking about the core stuff that all other good practices should derive from: DRY, YAGNI, the principle of least astonishment, clean separation of problem domains, writing to an interface, and writing human legible code are my personal core. Anything a little more complex that advocates the abandonment of those practices should be considered Kool Aid in any language, but especially a language like JavaScript where it's powerfully easy to leave a legacy of very confusing code for the next guy. Loose coupling, for instance, is great stuff until you take it so far that you can't even tell where interaction between objects is happening.

Don't Fear Dynamic Typing

There aren't a lot of core types in JavaScript. For the most part, dynamic casting rules are practical and straight-forward but it pays to learn them so you can better learn to manage data flow without needless casts and pointless validation routines. Trust me. Strict types are great for performance and spotting problems on compile but they don't protect you from anything.

Learn the Crap out of JS Functions and Closures

JS's first-class functions are arguably the main reason JS won the "Only Language Worth Touching the Client-Side Web With Award." And yes, there actually was competition. They're also a central feature of JS. We construct objects with them. Everything is scoped to functions. And they have handy features. We can examine params via the arguments keyword. We can temporarily attach and fire them in the context of being methods of other objects. And they make event-driven approaches to things obscenely easy to implement. In short, they made JS an absolute beast at reducing complexity and adapting varying implementations of JS itself (but mostly the DOM API) right at the source.

Re-Evaluate Patterns/Practices Before Adopting

First class functions and dynamic types render a lot of the more complex design patterns completely pointless and cumbersome in JS. Some of the simpler patterns, however, are incredibly useful and easy to implement given JS's highly flexible nature. Adapters and decorators are particularly useful and I've found singletons helpful for complex ui widget factories that also act as event-managers for the ui elements they build.

Follow the Language's Lead and Do More With Less

I believe one of the Java head honchos makes the argument somewhere that verbosity is actually a positive feature that makes code easier to understand for all parties. Hogwash. If that were true, legalese would be easier to read. Only the writer can make what they've written easier to understand and you can only do that by putting yourself in the other guy's shoes occasionally. So embrace these two rules. 1. Be as direct and clear as possible. 2. Get to the damn point already. The win is that clean, concise code is orders of magnitude easier to understand and maintain than something where you have to traverse twenty-five layers to get from the trigger to the actual desired action. Most patterns that advocate that sort of thing in stricter languages are in fact workarounds for limitations that JavaScript doesn't have.

Everything is Malleable and That's Okay

JS is probably one of the least protectionist languages in popular use. Embrace that. It works fine. For instance you can write objects with inaccessible persistent "private" vars by simply declaring regular vars in a constructor function and I do this frequently. But it's not to protect my code or users of it "from themselves" (they  could just replace it with their own version during run-time anyway). But rather it's to signal intent because the assumption is that the other guy is competent enough to not want to mangle any dependencies and will see that you're not meant to get at it directly perhaps for a good reason.

There Are No Size Limits, Only Problem Domains

The biggest problem I have with all the Java codebases I've seen is an overabundance of class files. First of all SOLID is just a confusing reiteration of what you should already know about OOP. A class should handle a specific set of related problems. Not one problem with one method. That's just taking bad old chaining func-spaghetti C code only with the addition of all the pointless class syntax to boot. There is no size or method limit. If it makes sense to add something to an already long function or class or constructor, it makes sense. Take jQuery. It's an entire library-length toolset in a single function and there is nothing wrong with that. Whether we still need jQuery is up to reasonable debate but in terms of design, you can learn a hell of a lot about how to write effective JavaScript by understanding how JQ is architected for minimal memory usage/performance impact through slick use of closures and the prototype property.

If Java is All You Know, Dabble in Something With a Non-C-Based Syntax

When I started messing with Python because I liked what I was hearing about Django, I learned to start separating syntax from language design. As a result, it became easier to understand Java and C as a sum of their language design parts rather than a sum of things they do differently with the same syntax. A nice side-effect is that the more you understand other languages in terms of design, the better you'll understand the strengths/weaknesses of the one you know best through contrast.

Conclusion

Now, considering all of that, lets hit all your problem-points:

No immediate way of finding a function's entry point (other than a plain text search, which may then result in a subsequent searches for methods further up the call hierarchy, after two or three of which you've forgotten where you started)

Chrome and Firebug do actually have call-tracing. But see also my points on structure and keeping things concise and direct. The more you can think of your app as larger well-encapsulated constructs interacting with each other, the easier it is to figure whose fault it is when things go wrong. I'd say this is true of Java too. We have class-like function constructors that are perfectly serviceable for traditional OOP concerns.

function ObjectConstructor(){
    //No need for an init method.
    //Just pass in params and do stuff inside for instantiation behavior

    var privateAndPersistent = true;

    //I like to take advantage of function hoisting for a nice concise interface listing
    this.publicAndPointlessEncapsulationMurderingGetterSetter
    = publicAndPointlessEncapsulationMurderingGetterSetter;
    //Seriously though Java/C# folks, stop with the pointless getter/setters already

    function publicAndPointlessEncapsulationMurderingGetterSetter(arg){
        if(arg === undefined){
            return privateAndPersistent;
        }
        privateAndPersistent = arg;
    }

}

ObjectConstructor.staticLikeNonInstanceProperty = true;

var instance = new ObjectConstructor();//Convention is to  capitalize constructors

In my code, I almost never use the object literals {} as structural app components since they can't have internal (private) vars and prefer instead to reserve them for use as data structures. That helps set an expectation that maintains clarity of intent. (if you see curlies, it's data, not a component of app architecture).

Parameters are passed in to functions, with no way of knowing what properties and functions are available on that parameter (other than actually running the program, navigating to the point at which the function is called, and using console.logs to output all the properties available)

Again, see modern browser tools. But also, why is it such a bummer to run the program again? Reload is something a client-side web dev typically hits every few minutes because it costs you absolutely nothing to do it. This is again, another point that app structure can be helpful with but it is one down-side tradeoff of JS that you have to run your own validation when enforcing contracts is critical (something I only do at endpoints exposed to other things my codebase doesn't control). IMO, the tradeoff is well worth the benefits.

Common usage of anonymous functions as callbacks, which frequently leads to a spaghetti of confusing code paths, that you can't navigate around quickly.

Yeah that's bad on anything non-trivial. Don't do that. Name your functions kids. It's easier to trace things as well. You can define, evaluate (required to assign), and assign a simple trivial function in-line with:

doSomethingWithCallback( (function callBack(){}) );

Now Chrome will have a name for you when you're tracing through calls. For non-trivial func I would define it outside of the call. Also note that anonoymous functions assigned to a variable are still anonymous.

And sure, JSLint catches some errors before runtime, but even that's not as handy as having red wavy lines under your code directly in the browser.

I never touch the stuff. Crockford's given some good things to the community but JSLint crosses the line into stylistic preferences and suggesting certain elements of JavaScript are bad parts for no particularly good reason, IMO. Definitely ignore that one thing about regEx and negation classes followed by * or +. Wildcards perform more poorly and you can easily limit the repetition with {}. Also, ignore anything he says about function constructors. You can easily wrap them in a factory func if the new keyword bothers you. CSSLint (not Crockford's) is even worse on the bad advice front. Always take people who do a lot of speaking engagements with a grain of salt. Sometimes I swear they're just looking to establish authority or generate new material.

And again, you must unlearn what you have learned with this run-time concern you have. (it's a common one I've seen with a lot of Java/C# devs) If seeing errors in run-time still bothers you 2 years later, I want you to sit down and spam reload in a browser until it sinks in. There is no compile-time/run-time divide (well not a visible one anyway - JS is run on a JIT now). It's not only okay to discover bugs at run-time, it's hugely beneficial to so cheaply and easily spam reload and discover bugs at every stopping point you get to.

And get crackin' on those Chrome dev tools. They're built-in directly to webkit. Right-click in Chrome. Inspect element. Explore the tabs. Plenty of debug power there with the ability to alter code in the console during run-time being one of the most powerful but less obvious options. Great for testing too.

On a related note, errors are your friends. Don't ever write an empty catch statement. In JS we don't hide or bury errors (or at least we shouldn't cough YUI /cough). We attend to them. Anything less will result in debug pain. And if you do write a catch statement to hide potential errors in production at least silently log the error and document how to access the log.


问:
Assertions vs Exceptions - is my understanding of the differences between the two correct?

Design By Contract uses preconditions and postconditions of the public
  methods in a class together to form a contract between the class and
  its clients.

a) In code we implement preconditions and postconditions either as assertions or as exceptions?

b) We implement preconditions and postconditions in code as exceptions if not fulfilling preconditions or postconditions doesn't indicate logically impossible situations or programming errors?

c) we implement them in code as assertions when not fulfilling preconditions or postconditions does indicate logically impossible situations or programming errors?

d) Should preconditions and postconditions only be defined on public methods?

EDIT:

Aren't the following checks considered to be part of a normal operation ( and as I already mentioned, I've seen plenty of articles on DbC using similar examples for preconditions, where checks were made against arguments supplied by the user ), since if the user enters bad data, then without checks operation won't be rejected and as such system will stop working according to specs:

Link:

```<code>public User GetUserWithIdOf(int id,
        UserRepository userRepository) {
  // Pre-conditions
  if (userRepository == null)
      throw new ArgumentNullException(
          "userRepository");
  if (id <= 0)
      throw new ArgumentOutOfRangeException(
          "id must be > 0");

  User foundUser = userRepository.GetById(id);

  // Post-conditions
  if (foundUser == null)
      throw new KeyNotFoundException("No user with " +
          "an ID of " + id.ToString() +
          " could be located.");

  return foundUser;
}
</code>```

答:
You should define them as assumptions, (in debugging as assertions) so if the pre or post condition isn't true then you have an logical error in in your program.

The key point here is avoiding the test in production code to speed it up,

for example a binary search can go in O(log n) time only if the array is already sorted (precondition) but testing this (for the exception) takes O(n) so if you test for that you might as well go for the linear search and get an early return out of it.

They can be defined on any piece of code (i.e. anything that can be extracted into a method).


答:
a) In code we implement preconditions and postconditions either as assertions or as exceptions?

Strictly, no.  The pre/postcondition is actually the test that raises the exception.  The exception is merely the way of saying that pre/postcontion has been violated.

b) We implement preconditions and postconditions in code as exceptions if not fulfilling preconditions or postconditions doesn't indicate logically impossible situations or programming errors?

No.  People often use explicit test / raise exception code to indicate a bug, etc.

c) we implement them in code as assertions when not fulfilling preconditions or postconditions does indicate logically impossible situations or programming errors?

You can do.  But see above.

d) Should preconditions and postconditions only be defined on public methods?

No.  If you are using them (formally) there is no reason to restrict them to public methods.

Actually, the key difference between the two approaches is that you can (typically) turn off checking of the "assertion" style of pre/postconditions (e.g. Java's assert statements) when you move your code into production.  In the case of Java, this is typically done using a JVM command line option.

This means that you shouldn't use assertion style pre/postconditions for checks that are part of "normal operation" ... like validating user input.  In fact, you probably shouldn't treat them as pre/postconditions at all.  They are part of the program's active functionality (for the lack of a better way of describing it ...)

Title: Assertions vs Exceptions - is my understanding of the differences between the two correct?

Body:
Design By Contract uses preconditions and postconditions of the public
  methods in a class together to form a contract between the class and
  its clients.

a) In code we implement preconditions and postconditions either as assertions or as exceptions?

b) We implement preconditions and postconditions in code as exceptions if not fulfilling preconditions or postconditions doesn't indicate logically impossible situations or programming errors?

c) we implement them in code as assertions when not fulfilling preconditions or postconditions does indicate logically impossible situations or programming errors?

d) Should preconditions and postconditions only be defined on public methods?

EDIT:

Aren't the following checks considered to be part of a normal operation ( and as I already mentioned, I've seen plenty of articles on DbC using similar examples for preconditions, where checks were made against arguments supplied by the user ), since if the user enters bad data, then without checks operation won't be rejected and as such system will stop working according to specs:

Link:

```<code>public User GetUserWithIdOf(int id,
        UserRepository userRepository) {
  // Pre-conditions
  if (userRepository == null)
      throw new ArgumentNullException(
          "userRepository");
  if (id <= 0)
      throw new ArgumentOutOfRangeException(
          "id must be > 0");

  User foundUser = userRepository.GetById(id);

  // Post-conditions
  if (foundUser == null)
      throw new KeyNotFoundException("No user with " +
          "an ID of " + id.ToString() +
          " could be located.");

  return foundUser;
}
</code>```


问:
What are the 'must know' Emacs commands?
I'm a fairly new convert to Emacs and I really love it as an editor, primarily because I keep finding new and super-useful commands. Are there any other programmer 'must known' commands missing from my list?</p>

```<code>M-x replace-string     - Find and replace a given string.
M-x goto-line          - Goto a specific line
M-x column-number-mode - Show the current column number in text bar
</code>```

答: Try doing the tutorial (C-h t).  It teaches you a lot of the fundamental keybindings, and THEN you can start looking for even more fun ones.</p>

ContentLicense: CC BY-SA 2.5


问:
Best strategy in SQL
Recently, a colleague told me that it wasn't advisable to make conditions in the join clauses. Instead he suggested to make conditions in the where clause. He told me that the SQL engine was optimized for this way.

Here is a simple example to illustrate my question. In this case, I think it would make any difference.

What strategy is the best? And why?

Assume we have a parameter nammed @user_id.

First strategy

```<code>SELECT      role.name
FROM        user_role
INNER JOIN  user ON user_role.user_id = user.id AND
                    user_role.user_id = @user_id
INNER JOIN  role ON user_role.role_id = role.id
</code>```

Second strategy

```<code>SELECT      role.name
FROM        user_role
INNER JOIN  user ON user_role.user_id = user.id
INNER JOIN  role ON user_role.role_id = role.id
WHERE       user.id = @user_id
</code>```

答:
The two queries you gave are not equivalent.  In the second, user_role.user_id is explicitly linked to user.id, whereas in the first, there's no link between the user table and the user_role table.  (What database are you using for that, BTW?  An inner join with no linkage to the existing query contents doesn't look like valid SQL to me.)

Your friend is right, BTW.  JOIN criteria are supposed to be for specifying the linkage between the tables.  It affects the way one entire table relates to another entire table.  Filtering (selecting which rows within a table are valid) should go in the WHERE clause.

EDIT: In response to the comment:

I understand what you say, but I still think that the first strategy
  is more efficient because all the lines are not loaded. Probably
  you're right, but I would understand why.

First, if by "lines" you mean "rows" or "records in the table," it's highly unlikely that all the lines will be loaded as part of the JOIN anyway.  That would be highly inefficient, but only a really horrible database engine would do that.

The SQL engine uses a process known as relational algebra to transform the query you write into the optimum method for retrieving the data you're querying for.  Just like the algebra you learned in school, it can involve moving terms around from one place to another under specific rules that ensure that everything stays equivalent in the final result.

As DFord mentioned in his comment, the DBMS will probably end up producing the same query plan from both styles. If you want to test it, try running the query plans of both queries (the mechanism to do this varies from one DBMS to another; you'll have to look up how it's done on your system) and comparing them.

That being true, the real reason to write your joins in the second style is not efficiency of execution, but efficiency of maintenance.  If someone needs to read your query at some later point, and they're familiar with standard SQL style, it will be a lot easier for them to understand if your query is written in standard SQL style too, which means using the JOIN criteria to specify linkage and the WHERE clause to specify filtering.

Title: Best strategy in SQL


问:
Custom Alphabetic Sorting of Array in Java
I have a requirement to read a text file with lines in tag=value format and then output the file with specific tags listed first and the rest sorted alphabetically.  The incoming file is randomly sorted with the exception of the first line.  The output needs the first two lines to always be the same.  For example, given the following tags:

```<code>NAME
AGE
SSN
MARITAL_STATUS
NO_OF_DEPENDENTS
</code>```

The input will always have NAME first and the remaining tags (there are literally hundreds) sorted randomly.  The output needs to have SSN first and NAME second and the rest sorted alphabetically so I would end up with:

```<code>SSN
NAME
AGE
MARITAL_STATUS
NO_OF_DEPENDENTS
</code>```

Note: These are just sample tags.  The actual file has 13 fields which need to be listed first and the remaining few hundred listed alphabetically.

I'm trying to figure out the best way to do the sorting.  Right now my plan is to read the lines in the incoming file and marshal them into two List objects.  The first will contain the specific tags which need to be placed first and the second will have everything else.  I will then sort the second list and merge it into the first list.  This seems complicated and I feel like I'm missing an easier or more elegant approach.

答:
The data that is present most closely resembles a map of header to rest of value.  This should point one in the direction of a Map rather than a List.

Of the data that is presented, there are two groupings of the data - the first 13 fields, and all the rest.  The presentation of the all the rest is to be used in a sorted order.  For this, one looks at the SortedMap interface and sees the TreeMap as one if its implementations.

The 13 field data can be used as a little known map type - the EnumMap.

With the EnumMap, one would first define the enumerations of the fields in the order desired.

```<code>public enum Headers {
    SSN,
    NAME;
}
</code>```

One then gets the associated code that looks something like (lacking the looping over the data):

```<code>SortedMap<String, String> other = new TreeMap<String, String>();
EnumMap<Headers, String> headers = new EnumMap<Headers, String>(Headers.class);
try {
    headers.put(Headers.valueOf(key), value);
} catch (IllegalArgumentException  e) {
    other.put(key, value);
}
</code>```

If the header is present in the enum, put it in the headers map, otherwise put it in the other map.

At this point, one can then iterate over the headers EnumMap and then the other TreeMap printing out the key and value pairs.  Or present a new object that itself extends Iterable and makes an iterator that first walks the EnumMap and then the SortedMap.

The enum provides easy extensibility of the code (if you want to do validation checking, one can associate it with the enum.  See the Java tutorial on Enum Types to see some more things one can do with it (associate a method with the enum itself, associate values (Pattern? an instance of a class that has an interface providing a boolean validate(String arg)? display formatting code?) to further extend it.

Body:
The data that is present most closely resembles a map of header to rest of value.  This should point one in the direction of a Map rather than a List.

Of the data that is presented, there are two groupings of the data - the first 13 fields, and all the rest.  The presentation of the all the rest is to be used in a sorted order.  For this, one looks at the SortedMap interface and sees the TreeMap as one if its implementations.

The 13 field data can be used as a little known map type - the EnumMap.

With the EnumMap, one would first define the enumerations of the fields in the order desired.

public enum Headers {
    SSN,
    NAME;
}

One then gets the associated code that looks something like (lacking the looping over the data):

SortedMap<String, String> other = new TreeMap<String, String>();
EnumMap<Headers, String> headers = new EnumMap<Headers, String>(Headers.class);
try {
    headers.put(Headers.valueOf(key), value);
} catch (IllegalArgumentException  e) {
    other.put(key, value);
}

If the header is present in the enum, put it in the headers map, otherwise put it in the other map.

At this point, one can then iterate over the headers EnumMap and then the other TreeMap printing out the key and value pairs.  Or present a new object that itself extends Iterable and makes an iterator that first walks the EnumMap and then the SortedMap.

The enum provides easy extensibility of the code (if you want to do validation checking, one can associate it with the enum.  See the Java tutorial on Enum Types to see some more things one can do with it (associate a method with the enum itself, associate values (Pattern? an instance of a class that has an interface providing a boolean validate(String arg)? display formatting code?) to further extend it.


问:
What needs to change for Software Engineering to become a formal profession?
Unlike other professions (such as Accounting, Law, Medicine, etc.), there is no profession-wide certification for Software Engineering.

I am well aware of the multitude of technology and methodology specific certifications that aim to serve as proof of specialisation and experience, but there is no public Software Engineering society / governing body that sets (and has the power to legally assess) generally accepted professional standards.

I understand that software is a dynamic beast - that is part art, part science - but I'm wondering whether Software Engineering has the potential to become a formal profession.

What needs to change for this to happen, and would it even be a good thing?

(If anybody knows of formal research into this topic I'd greatly appreciate references)

Update

I agree with many of the good points raised below regarding the current level of certification in Software Engineering. I also find it very interesting that some countries treat Software Engineering as a profession whilst others don't.

There does however seem to be a bit of shroud surrounding the term "formal profession", and how it would apply to Software Engineering. I think the key issue with Software Engineering - and the primary reason it is not a full-blown profession - is that if you're a certified Software Engineer, and - for example - some software you wrote for an elevator malfunctions and kills people, your certification and / or membership to a formal professional body won't get revoked.

Sure, your company might get sued for millions, and you personally might lose your job and earn a bad reference, but generally speaking, you personally are protected by the shield of limited liability as a result of being employed by said company. In other words, and as far as I know, there is no legal assessment / enforcement in place (unlike other formal professions and their governing societies) which have the mandate to officially bar you from trading once you've made a colossal stuff-up.

I quite liked the answer that touched on the fact that Software Engineering - as it stands - is a meritocracy, which doesn't need to be a formal profession, and that this is a good thing that shouldn't change. At the same time, I think we need to make a clear distinction between Software Engineers of mission-critical software versus developers of miscellaneous / non-critical software.

To those of you who work / have worked on mission-critical software - is there any personal liability? Surely there is a need for formal repercussions in the event of the Software Engineer making a costly mistake?

答:
Software is not a profession, nor will it ever be one.

"A profession arises when any trade or occupation transforms itself through the development of formal qualifications based upon education, apprenticeship, and examinations, the emergence of regulatory bodies with powers to admit and discipline members, and some degree of monopoly rights."

That description doesn't match software at all.

First off, anyone with an interest in software can go out and try to find a job developing software. Many of those people have college degrees totally unrelated to computer programming and many have no degree at all. There's nothing stopping either of those groups from becoming software programmers.

Software can't become a profession because "licensed" members become responsible for damage they cause and their malpractice. 80-90% of developers will lose their job within a couple of years for that one alone.

In general, software quality is atrocious, bug prone and just plain not very well done. Is that worthy of being a profession? Do you foresee that stopping because people get licensed? If a professional organization isn't going to stand for high standards and professional quality then there's no point to it. That goes directly against industry practice. Writing quality, robust and working software is against the principles of most of the companies out there, because time-to-market, cost, it is good enough, don't want to break anything else trying to fix broken software is viewed as more important than professional grade software.

Also, regarding malpractice. How are you going to prove that one develper versus another is to blame. In software it is way to easy to point fingers and both developers "are right". Who is to blame when that developer uses the undocumented API hidden in the bowels of the OS and then the OS vendor changes its function or removes it?

Good luck with that regulatory body thing. Let's see congress say no to Microsoft when Microsoft asks them to kill that bill because it will only allow them to hire "licensed" developers. Without that regulatory body, then who is going to join an organization that has the right to discipline you and charge you dues especially if there is no added value like getting monopoly rights without the regulatory body.

As for, would it be a good thing to require licensing? Absolutely, for those who can get accredited. Your pay would rise dramatically with your new found monopoly.

However, for everyone else...the use of computer technology in businesses would probably decline along with the fast pace of advancement we see nowadays. There will certainly be barriers to new software advances, such as languages and design methodologies. After all, who is going to want to push for new ways of doing things that will require years of retraining in order to maintain your license. Most licensed developers will prefer to keep things just the way they are in that regard.


答:
They are Both Wrong, This is the Correct way :

```<code>SELECT u.UserName,r.RoleName
FROM user u
Left JOIN  user_role ur ON ur.user_id = u.id
Left JOIN  role r ON r.id= ur.role_id
WHERE u.id = @user_id
</code>```

Anything other than is SQL BLASPHEMY!

(I looked at your SQL for 20 min and i still don't know what you expected it to do or return)

Edit: Adding in some of the comments below as there is some good stuff there:

Q) Why are you advocating left joins here as the Only True Way?

A) Because what good is role name by its self? You clearly want the User with Role Name combination. The left joins insure that no users are missed (in case a user does not have a role or if there is a relational integrity issue)
Think about it.. With inner joins how do you know if you have a bad userid or if the user doesn't have a role? –

Q) You know there are no "relational integrity issues" because you have a FK constraint in place and the database takes care of that for you. (If you don't, then that's SQL heresy!) And since what's being queried for here is the set of all role names for a specific user, if the user doesn't have any roles, then an empty set is a perfectly valid response. (And a more correct one than a set containing a single element whose value is NULL, which is what your scenario would yield.)

A) You often need to query foreign systems that break every rule in the book. That's a fact of life. Code defensively, and keep good habits. -  I reiterate if the user doesn't exist this query returns a value that the runner will interpret incorrectly that as “The user doesn't have a role”

Title: Best strategy in SQL

Body:
Recently, a colleague told me that it wasn't advisable to make conditions in the join clauses. Instead he suggested to make conditions in the where clause. He told me that the SQL engine was optimized for this way.

Here is a simple example to illustrate my question. In this case, I think it would make any difference.

What strategy is the best? And why?

Assume we have a parameter nammed @user_id.

First strategy

```<code>SELECT      role.name
FROM        user_role
INNER JOIN  user ON user_role.user_id = user.id AND
                    user_role.user_id = @user_id
INNER JOIN  role ON user_role.role_id = role.id
</code>```

Second strategy

```<code>SELECT      role.name
FROM        user_role
INNER JOIN  user ON user_role.user_id = user.id
INNER JOIN  role ON user_role.role_id = role.id
WHERE       user.id = @user_id
</code>```

Body:
They are Both Wrong, This is the Correct way :

SELECT u.UserName,r.RoleName
FROM user u
Left JOIN  user_role ur ON ur.user_id = u.id
Left JOIN  role r ON r.id= ur.role_id
WHERE u.id = @user_id

Anything other than is SQL BLASPHEMY!

(I looked at your SQL for 20 min and i still don't know what you expected it to do or return)

Edit: Adding in some of the comments below as there is some good stuff there:

Q) Why are you advocating left joins here as the Only True Way?

A) Because what good is role name by its self? You clearly want the User with Role Name combination. The left joins insure that no users are missed (in case a user does not have a role or if there is a relational integrity issue)
Think about it.. With inner joins how do you know if you have a bad userid or if the user doesn't have a role? –

Q) You know there are no "relational integrity issues" because you have a FK constraint in place and the database takes care of that for you. (If you don't, then that's SQL heresy!) And since what's being queried for here is the set of all role names for a specific user, if the user doesn't have any roles, then an empty set is a perfectly valid response. (And a more correct one than a set containing a single element whose value is NULL, which is what your scenario would yield.)

A) You often need to query foreign systems that break every rule in the book. That's a fact of life. Code defensively, and keep good habits. -  I reiterate if the user doesn't exist this query returns a value that the runner will interpret incorrectly that as “The user doesn't have a role”


问:
How can you prove an acyclic graph has n-1 edges?
I'm not so hot on the maths for this but for what I understand...

A graph g exists with v vertices and edges. g = (V,E);

The spanning graph for this is an acyclic copy of this where all the vertices are present, and all the edges are a subset of the graph with the condition that each connection is distinct.

Apparently the MST should have n-1 nodes. How can this be proven ?

Sources:

http://youtu.be/zFbq8vOZ_0k?t=25m1s

http://www.gtkesh.com/minimum-spanning-tree/

答:
Consider any minimum spanning tree.
Choose some vertex as the root.
Then each vertex has one parent, except the root.</p>


问:
What are the worst false economies in software development?
What are the worst false economies (that is ways of saving money that ultimately cost more than they save) prevalent in the software industry and how do you combat them?</p>

答:
Long feedback loops!

It happens to everybody: you build something that you think is awesome, and it turns out you were wrong. That isn't the problem. The problem is how long you spend building before finding out that you should stop.

At the high level, you see this problem with long release cycles. If you build for a year without feedback, you're gambling the whole year. The more often you release, the smaller your gambles, and the better you get at gambling.

But it also happens at the lowest levels. As a developer, I really like frequent code reviews (or, better, pair programming) because it limits the amount of time I can continue doing something dumb before somebody says, "Hey, there's a simpler way!" For the same reason, I like my unit tests to run quickly and frequently, so I can catch and kill bugs before they grow.

Once you start noticing the importance of short feedback loops, you'll see it everywhere. E.g., the military notion of the OODA loop.


答:
Proof by induction:

Every acyclic graph can be represented as a tree, if all the nodes are connected.

So let's think about trees.  You've got one root node.  Let's look at the simplest, case, in which the tree only has one branch, and so it's a simple linked list.

If there are two nodes, there's one edge between them.  Add one node to the end of the linked list, and there are three nodes and two edges, and so on.

Now if we take the linked list and add another node to one of the nodes in the middle, we have a true tree.  And again, we're adding one node along with one edge.  Add another one, and it's the same.

No matter how many nodes you add, or where you add them, as long as it remains an acyclic, fully connected tree, there will always be N-1 edges for N nodes.

Title: How can you prove an acyclic graph has n-1 edges?

Body:
I'm not so hot on the maths for this but for what I understand...

A graph g exists with v vertices and edges. g = (V,E);

The spanning graph for this is an acyclic copy of this where all the vertices are present, and all the edges are a subset of the graph with the condition that each connection is distinct.

Apparently the MST should have n-1 nodes. How can this be proven ?

Sources:

http://youtu.be/zFbq8vOZ_0k?t=25m1s

http://www.gtkesh.com/minimum-spanning-tree/


问:
How to handle many arguments in an API wrapper?
I'm writing a PHP API wrapper for a third party API.  I want to make all the methods consistent, but I'm not sure how to handle the number of arguments some API routes accept.  One API request accepts up to 30 arguments.  Obviously, it would be unwieldy to list each argument as a parameter on the method.  Currently, I'm writing it to accept the required arguments as method paramaters, while all the optional ones are accepted in a final "additionalOptions" array.

```<code>public function sampleApiMethod($reqVal1, $reqVal2, $additionalOptions) {
    //Method Code
}
</code>```

Unfortunately, there are API requests that have only optional arguments.  In this case, either the only parameter is the array of options, or the method has individual parameters for optional arguments.  When only passing an array, the method is consistent with the other methods, but it's not the most intuitive.  With the latter option, I lose the consistent structure.  Is there any sort of best practice or structure for an API wrapper  that I should follow to try to have a consistent developer usage experience?

答:
There are a couple good ways to handle this and it really comes down to your personal preference and just how complex your API interface really is.  For a simple complexity interface I would increase the number of functions to be just the most specific calls to a given set of use cases.  You might be lucky and find that if there are only 10 different use case actions where an actor might need different combinations of required and optional arguments then one might just create ten different functions for this.

This may not be the best solution however if there are a large combination of arguments and use cases to consider.

Check out the Builder Pattern

The premise of the Builder pattern is that your object class will contain a special builder class object that can construct your object through function calls that return the same object.  This allows for fluid code that is much more verbose and clear to a client of the API.  This can be much more useful in representing a function's parameters than an extremely long list of arguments and prevents the common problem of a client accidentally mismatching arguments.  The client is forced to be verbose in building his arguments.

sendPizza (  pizzaBuilder->buildPeppers()->buildSausage()->etc...)

One is able to instantly look at the client code and decipher the breadth of arguments passed to sendPizza.


答:
I think performing manual code reviews is... well... kinda 80's. Well, maybe 90's.

In this modern era of continuous integration and online code review systems, you really don't want to hold back any code commits just because you're afraid that "it might break source control".

Come on, people. That's what changeset (or change lists) are for. You make your programmers feed the hungry maws of your source control system. Then your continuous integration server kicks in with a litany of targeted builds (well, hopefully just the daily build, but some of us get carried away). If anything breaks, you put the code monkey trophy (usually a plastic toy that someone found from a Lucky Charms cereal box) on the perpetrator's desk, and roll back the breaking change list. Well, some continuous integration systems automatically blasts out email/IM/desktop notifications to everyone in the team/department/organization that the build is broken, along with a nifty hyperlink to show everyone who exactly broke the build in which file or test. It's now the hapless programmer's job to fix whatever broke the compile/unit test/integration test/etc.

As this process runs on, the code review system kicks in (again, triggered by the check in). A list of qualified team members are notified of the change list being committed to source control, a review is started in the review system, and everyone starts to make annotations to the changes in the change list. Hopefully everyone will say "LGTM". If the programmer is smart, he will remember to pray/bribe/hide. If there are serious issues, the reviewers can create a defect (which can be hooked into the bug tracking system), or even require the changelist to be backed out. Yes, backed out changes hurt not only the ego, but the mind, that is true. It is a good seasoning on the junior developers, to reintegrate rejected change lists.

If your dev environment is lacking a CI or a code review system, you should seriously investigate these. A couple of links might help you:

Atlassian Crucible

JetBrains TeamCity

reitveld

Cruise Control

If you're going to get a CI server, you should also seriously think about unit test frameworks. If you're a C# dev, look into something like NUnit to get started.

Title: What should I do when waiting for a review?

Body:
Before asking my question, I must explain the situation.

I'm working for a company as a junior software engineer. One of the seniors always stops me when I have finished my development and want to commit.

He always wants me to wait for him to review it. This is ok, because usually he finds some bugs, and does some optimizations.

However I must commit my code before the deadline. When I finished, I call him and say it is finished. He usually comes late. So my code is late too.

My question is, what should I do? Should I wait him for a review?

EDIT: Addition to the question. I'm curious about one more issue.

I want to be free when coding. How could I gain the trust for freedom of development?

Some explanations:
I've talked with him about this. But it didn't help. We use an issue tracker already, but there isn't any task for reviews. There are just development and test tasks.


答:
Not a full answer on its own, just an addition to the excellent answers above...

Do you review your own code before checking it in?  I know it's not the most fun, but I try to make myself do it most of the time.  I have been programming professionally for 20 years (34 years total), but I usually find at least one bug and/or one thing I forgot, or could at least make better.  I agree with the sentiment that your code should always be reviewed and that a second set of eyes is better than one pair.  But even the same pair going over the code twice is better than once.

Do you write unit tests for your code?  In addition to unit tests, I also have a little shell script that searches for the most common mistakes I personally make.  Some of it is English grammar and spelling, some is coding issues that the compiler doesn't catch.  I run it before checking in large changes as a courtesy to everyone downstream.

I normally let people write their code and occasionally complain about it later, but I don't review every single check-in.  I once worked with a very junior programmer whose code I had to review and usually undo because they made so many mistakes.  That didn't end well.  You are in a profession where it's often more important to get it done right than done on time.  If you learn from your mistakes, you will go far.

If you can minimize the number of changes your reviewer needs to make to your code, you maximize the chance that they will trust you to write code that doesn't always need to be reviewed so carefully.  If you want freedom from reviews, take the maximum responsibility for the quality of your own output.

Some or all of these suggestions could be done while waiting for someone else to review your code.


答:
I like that you separate out the required options from the optional ones.  If you don't use a Builder, then for optional parameters, even when there are no required parameters, I'd definitely use an associative array or "map".  I think you are calling this just an "array" because PHP calls it that, but I'm not sure.

Builder Pattern lets you build the most airtight API, as @maple_shaft said.  It prevents clients from entering invalid keys into the parameter array and its functional nature lets you fail fast as soon as an invalid value is passed.  I would agree that that would be the best answer in most cases.

But the Builder pattern can require a fair amount of up-front programming work to make your API easy to use for your clients.  It may not be as PHP-ish as your associative arrays - I wouldn't know.  For completeness I feel I should mention some other options.  The first one may be what you are doing already...

Named Parameter Map

```<code>class MyApi {
    const Param1Name = 0;
    const Param2Name = 1;
    // etc.

    public function sampleApiMethod($myParamHash) {
        //Method Code
        $localParam1 = $myParamHash[Param1Name]
    }
}

// Load up params using pre-defined symbolic names to prevent typos
$myParamHash = array (MyApi::Param1Name => 5,
                      MyApi::Param2Name => 9);

// call method
sampleApiMethod($myParamHash);
</code>```

The beauty of this option (or the builder) is that it makes it clear which parameter is which, thus avoiding a lot of potential errors.

Default Values

I just did a quick search, and it seems that PHP supports default values for arguments.  These are probably better than Telescoping Methods, but there may be some cases where telescoping works and default values don't so I'll mention...

Telescoping Methods

Not sure if this works in php, but Something like:

```<code>public function sampleApiMethod($reqVal1, $reqVal2, $additionalOptions) {
    //Method Code
}
public function sampleApiMethod($reqVal1, $reqVal2) {
    sampleApiMethod($reqVal1, $reqVal2, null);
}
public function sampleApiMethod($reqVal1) {
    sampleApiMethod($reqVal1, null, null);
}
</code>```

I'm using "null" for default values.  But for an API, this makes things much easier on the caller without the work of creating a builder.  Just put the most commonly used arguments first and provide sensible defaults in your telescoping methods.

Re-Examine Your Model

Almost all useful programs model some real-world things or actions.  An API that takes 30 parameters strikes me as a red flag that there may be some higher-level design issues in your API.  You might want to provide a model for some of the things you are passing in as primitive values.  Functional people would model things in terms of functions, OO people in terms of objects.  Take your pick.

Title: How to handle many arguments in an API wrapper?

Body:
I'm writing a PHP API wrapper for a third party API.  I want to make all the methods consistent, but I'm not sure how to handle the number of arguments some API routes accept.  One API request accepts up to 30 arguments.  Obviously, it would be unwieldy to list each argument as a parameter on the method.  Currently, I'm writing it to accept the required arguments as method paramaters, while all the optional ones are accepted in a final "additionalOptions" array.

```<code>public function sampleApiMethod($reqVal1, $reqVal2, $additionalOptions) {
    //Method Code
}
</code>```

Unfortunately, there are API requests that have only optional arguments.  In this case, either the only parameter is the array of options, or the method has individual parameters for optional arguments.  When only passing an array, the method is consistent with the other methods, but it's not the most intuitive.  With the latter option, I lose the consistent structure.  Is there any sort of best practice or structure for an API wrapper  that I should follow to try to have a consistent developer usage experience?

Body:
I like that you separate out the required options from the optional ones.  If you don't use a Builder, then for optional parameters, even when there are no required parameters, I'd definitely use an associative array or "map".  I think you are calling this just an "array" because PHP calls it that, but I'm not sure.

Builder Pattern lets you build the most airtight API, as @maple_shaft said.  It prevents clients from entering invalid keys into the parameter array and its functional nature lets you fail fast as soon as an invalid value is passed.  I would agree that that would be the best answer in most cases.

But the Builder pattern can require a fair amount of up-front programming work to make your API easy to use for your clients.  It may not be as PHP-ish as your associative arrays - I wouldn't know.  For completeness I feel I should mention some other options.  The first one may be what you are doing already...

Named Parameter Map

class MyApi {
    const Param1Name = 0;
    const Param2Name = 1;
    // etc.

    public function sampleApiMethod($myParamHash) {
        //Method Code
        $localParam1 = $myParamHash[Param1Name]
    }
}

// Load up params using pre-defined symbolic names to prevent typos
$myParamHash = array (MyApi::Param1Name => 5,
                      MyApi::Param2Name => 9);

// call method
sampleApiMethod($myParamHash);

The beauty of this option (or the builder) is that it makes it clear which parameter is which, thus avoiding a lot of potential errors.

Default Values

I just did a quick search, and it seems that PHP supports default values for arguments.  These are probably better than Telescoping Methods, but there may be some cases where telescoping works and default values don't so I'll mention...

Telescoping Methods

Not sure if this works in php, but Something like:

public function sampleApiMethod($reqVal1, $reqVal2, $additionalOptions) {
    //Method Code
}
public function sampleApiMethod($reqVal1, $reqVal2) {
    sampleApiMethod($reqVal1, $reqVal2, null);
}
public function sampleApiMethod($reqVal1) {
    sampleApiMethod($reqVal1, null, null);
}

I'm using "null" for default values.  But for an API, this makes things much easier on the caller without the work of creating a builder.  Just put the most commonly used arguments first and provide sensible defaults in your telescoping methods.

Re-Examine Your Model

Almost all useful programs model some real-world things or actions.  An API that takes 30 parameters strikes me as a red flag that there may be some higher-level design issues in your API.  You might want to provide a model for some of the things you are passing in as primitive values.  Functional people would model things in terms of functions, OO people in terms of objects.  Take your pick.


问:
What Http verb should the route to log out of your web app be?
Browser support issues aside, if you're being an Http/hateoas stickler what verbs should the request to log into/out of a site be?

DELETE would seem like the obvious choice but I'm not sure what the resource you're deleting would be.

答:
Just want to clarify the accepted answer on how to logout, I use POST to a session resource (http://example.com/sessions/) for Login and the response includes a Location of the newly created session (http://example.com/sessions/a8edjn239sd8h2er).

For Logout, DELETE the session resource pointed by the Location from POST response.

You can Login/Logout multiple of times. Only first DELETE would return no content (204), after that it should return not found response (404). Logging in multiple times will create multiple sessions.


问:
Is the use of JUnit feasible for a short duration project of around 3 months?
I work on projects which are usually of a duration, not more than 3 months.
Recently there has been a discussion about the use of JUnit in the projects.
There are activities being planned related to that and, there could possibly be some kind of training too.
But I was wondering whether it is a good idea to use JUnit for such short term project?
Isn't JUnit more suited for longer duration projects?

I need to know this, so that I can inform my team well in advance before any crucial hours are spent.

答:
Duration of the project is irrelevant.

If you have a project that might only take a few hours, and you want automated, repeatable tests, then use of something like JUnit is justified. Heck, I've been happy creating unit tests even for throw-away projects. The point isn't how long the project is going to take, but how useful having automated tests is going to be.


答:
If you're positive your project will never be worked on ever again after those initial 3 months, then unit testing is less important.

If, on the other hand, it is quite possible that after some period of inactivity you require another development phase then unit testing is more important.

Your unit tests will really show their worth as automated regression tests.  Long after everybody has forgotten the ins and outs of the code, your unit tests will be able to tell you when you've messed something up.  They are an invaluable safety net in iterative projects.

Title: Is the use of JUnit feasible for a short duration project of around 3 months?

Body:
I work on projects which are usually of a duration, not more than 3 months.
Recently there has been a discussion about the use of JUnit in the projects.
There are activities being planned related to that and, there could possibly be some kind of training too.
But I was wondering whether it is a good idea to use JUnit for such short term project?
Isn't JUnit more suited for longer duration projects?

I need to know this, so that I can inform my team well in advance before any crucial hours are spent.


答:
Essentially the same as Mason and Mike have already said, but in different words...

If you have no edges, the most (connected) vertices you can have is one. Call this vertex the root.

To add a new vertex to a tree, you must also add a new edge (in order that the new vertex is connected). That edge can (and must) connect to any pre-existing vertex. The new vertex is a child of the pre-existing vertex, and we don't limit the number of children a parent can have.

If you start with just the root (1 vertex and 0 edges) you end up with 2 vertices and 1 edge. Repeat n times to get n+1 vertices and n edges.

This isn't a full proof in itself, but it's impossible to add edges or vertices in any other way (except that you could add two children at once, provided that you do it in a way that's equivalent to doing adding one first then the other). You can't add an edge without adding a vertex because doing so would complete a cycle. You can't add a vertex without adding an edge because that vertex wouldn't be connected to the tree.

BTW - for undirected graphs, words like "root", "parent" and "child" don't mean much, at least not formally. Any vertex in any undirected tree can be considered the root, and which vertex you happen to call the root decides for all edges which vertex is the parent and which is the child. My mental image of a tree tends to include identifying a particular vertex as the root, but that's arguably a misleading mental image.


问:
Use of pirated/cracked software for development
Disclaimer: I by no means condone the use of pirated software.

Have you ever witnessed the use of pirated software for development purposes? May be a company didn't have enough money to buy a piece of software and there were no free alternatives? May be a company wanted to try something out before buying and there were no trial licenses for that product. Whatever the circumstances, have you worked at a company where using pirated/cracked software was accepted? Were there any consequences to doing this?

答: It only takes one pissed of developer or IT staffer to bring a world of pain on your company if you do this. Nevertheless, I've worked in shops that pirated Microsoft Office because they didn't want to pay the added MSDN costs.</p>


答:
You tell him in advance when your code will be ready, not at the moment when it's done.
You should be able to determine that approx. one week ahead. That gives him time to prepare and plan the review so that it fits into both your plannings.


问:
Is there a de facto standard documentor for Javascript?
I'm trying to document my code using JSDOC3, that has a similar syntax to PHPDocumentator / Apigen. But is there a de-facto standard for Javascript inline documentation? I think Google Closure is the most complete (or so it seems), but what is widely adopted by IDEs and what most people expect to the docs to be?</p>

答: There's nothing which is as big as PHPDoc, but we're using airbnb, which already has over 2.000 stars and more than 350 forks on github, so it's used in a lot of projects.</p>


问:
Representing a parent/child hierarchy in a Relational Database
I am working on an application that connects to another application (Quickbooks) using an API by sending/receiving XML requests/responses.  I am able to work with the data in the XML response and load it into a datatable in c#, so that's not the issue.  What I am looking to do is write the data from the Quickbooks XML file to a relational database such as SQL Server so I can make it available to a web app or other applications.

The problem I am having is that for the Accounts object, there are multiple child entities (up to 5) for a given parent.  For example:

Parent: Revenues

Child: Charitable Donations

Sub-Child: Homeless Shelter

Sub-Sub-Child: Seattle Mission

Sub-Sub-Sub-Child: Food

This example is a bit extreme, as the particular file I'm working with only goes out to three levels, but a maximum of five is allowed by Quickbooks (thus I'm trying to come up with a solution that would scale well).  When I create my datatable in C# from the data in the XML file, I have two columns: ParentID, ChildID.  It would look like this:

```<code>ParentID     ChildID     Account               Balance
--------     -------     -------               --------
001          002         Revenues              45670
002          003         Charitable Donations   1500
003          004         Homeless Shelter        800
004          005         Seattle Mission         400
005          NULL        Food                    200
</code>```

In this example, I am able to determine all of the child IDs of a parent, and then look to the ParentID with that ChildID and see if that child has any children, etc.  I have a method which does a fairly good job of parsing through that, and it works fine for the time being, but is this really the best way to store it in a database if I wanted to permanently house the data in a relational database?  It seems like there should be a more elegant solution, but I'm not sure what that would be.

答:
If I understand you correctly, you have an Account entity where one Account can link to one or more other Accounts.

The canonical solution to store such a relation in a relational database is to give each row of the Accounts table a foreign key that links back to the parent entry in the table.

In your example, this would look like this:

```<code>ID  Parent  Account name          Balance
--- ------  ------------          -------
1   NULL    Revenues              45670
2   1       Charitable Donations   1500
3   2       Homeless Shelter        800
4   3       Seattle Mission         400
5   4       Food                    200
6   4       Housing                 100
</code>```

I have added an extra row to show how this scheme allows a parent to have multiple child entries.
By filtering on the right columns, you can retrieve both the parent and the children of each entry.

Body:
If I understand you correctly, you have an Account entity where one Account can link to one or more other Accounts.

The canonical solution to store such a relation in a relational database is to give each row of the Accounts table a foreign key that links back to the parent entry in the table.

In your example, this would look like this:

ID  Parent  Account name          Balance
--- ------  ------------          -------
1   NULL    Revenues              45670
2   1       Charitable Donations   1500
3   2       Homeless Shelter        800
4   3       Seattle Mission         400
5   4       Food                    200
6   4       Housing                 100

I have added an extra row to show how this scheme allows a parent to have multiple child entries.
By filtering on the right columns, you can retrieve both the parent and the children of each entry.


问:
Which design pattern is typically used when designing a WCF data services driven Winforms application?
Please excuse me as I am a bit new to the following technologies and practices.  I have been given the task to create a management suite utilizing an MDI GUI. This suite will be the front end to a WCF data service.  My question is, what design pattern is typically used by most professionals when designing such an application.  At the moment, I have been looking into both MVC and 3-tier design patterns.

If the MVC route tends to be taken, I'm assuming that because the WCF service is added as a service reference which provides visibility to all it's classes, the model part of MVC is pretty much covered?  Would it make sense to generate an interface from the WCF class?

If the 3-tier pattern is used, would it make sense to create datalayer objects for every visible WCF class (ex. PropertyDAL), and on top of that, business layer objects for each datalayer object? If this is the case, with there being over 114 classes which would be made visible, this would mean 228 additional classes which seems a bit bloated to me and not necessary.

Here is the link to the usage of MVC design pattern which has lead me to my question.

答:
This is an enormous question, people have written whole books on this. I will therefore attempt to keep my answer brief.

Comparing MVC to three-tier is like comparing apples to oranges. Quite simply they have totally different usages.

MVC is a presentation pattern. It will help you design your UI, but not really any further. It has the concept of a "model" which nicely abstracts things like physical data reads, physical data writes, business rules and all bar the simplest of validation.

A three-tier approach however is a higher level pattern which covers the whole of your system. You have the concept of presentation, business and data services. So you need to think about how you build these three services, and furthermore how they talk to each other.

Interestingly, MVC and Three Tier can easily coexist. If you imagine a three-tiered system, theres absolutely nothing to stop you writing your presentation services using MVC.


问:
Can/should the Single Responsibility Principle be applied to new code?
The principle is defined as modules having one reason to change. My question is, surely these reasons to change are not known until the code actually starts to change?? Pretty much every piece of code has numerous reasons why it could possibly change but surely attempting to anticipate all of these and design your code with this in mind would end up with very poor code. Isn't it a better idea to only really start to apply SRP when requests to change the code start coming in? More specifically, when a piece of code has changed more than once for more than one reason, thus proving it has more than one reason to change. It sounds very anti-Agile to attempt to guess reasons for change.

An example would be a piece of code which prints a document. A request comes in to change it to print to PDF and then a second request is made to change it to apply some different formatting to the document. At this point you have proof of more than a single reason to change (and violation of SRP) and should make the appropriate refactoring.

答:
Of course, the YAGNI principle will tell you to apply SRP not before you really need it. But the question you should ask yourself is: do I need to apply SRP first and only when I have to actually change my code?

To my experience, the application of SRP gives you a benefit much earlier: when you have to find out where and how to apply a specific change in your code. For this task, you have to read and understand your existing functions and classes. This gets very much easier when all your functions and classes have a specific responsibility. So IMHO you should apply SRP whenever it makes your code easier to read, whenever it makes your functions smaller and more self-describing. So the answer is yes, it makes sense to apply SRP even for new code.

For example, when your printing code reads a document, formats the document and prints the result to a specific device, these are 3 clear separable responsibilities. So make at least 3 functions out of them, give them according names. For example:

```<code> void RunPrintWorkflow()
 {
     var document = ReadDocument();
     var formattedDocument = FormatDocument(document);
     PrintDocumentToScreen(formattedDocument);
 }
</code>```

Now, when you get a new requirement to change document formatting or another one to print to PDF, you know exactly at which of these functions or locations in code you have to apply changes, and even more important, where not.

So, whenever you come to a function you don't understand because the function does "too much", and you are not sure if and where to apply a change, then consider to refactor the function into separate, smaller functions. Don't wait until you have to change something. Code is 10x more often read than changed, and smaller functions are much easier to read. To my experience, when a function has a certain complexity, you can always split the the function into different responsibilities, independent of knowing which changes will come in the future. Bob Martin typically goes a step further, see the link I gave in my comments below.

EDIT: to your comment: The main responsibility of the outer function in the example above is not to print to a specific device, or to format the document - it is to integrate the printing workflow. Thus, at the abstraction level of the outer function, a new requirement like "docs should not be formatted anymore" or "doc should be mailed instead of printed" is just "the same reason" - namely "printing workflow has changed". If we talk about things like that, it is important to stick to the right level of abstraction.

Body:
Of course, the YAGNI principle will tell you to apply SRP not before you really need it. But the question you should ask yourself is: do I need to apply SRP first and only when I have to actually change my code?

To my experience, the application of SRP gives you a benefit much earlier: when you have to find out where and how to apply a specific change in your code. For this task, you have to read and understand your existing functions and classes. This gets very much easier when all your functions and classes have a specific responsibility. So IMHO you should apply SRP whenever it makes your code easier to read, whenever it makes your functions smaller and more self-describing. So the answer is yes, it makes sense to apply SRP even for new code.

For example, when your printing code reads a document, formats the document and prints the result to a specific device, these are 3 clear separable responsibilities. So make at least 3 functions out of them, give them according names. For example:

 void RunPrintWorkflow()
 {
     var document = ReadDocument();
     var formattedDocument = FormatDocument(document);
     PrintDocumentToScreen(formattedDocument);
 }

Now, when you get a new requirement to change document formatting or another one to print to PDF, you know exactly at which of these functions or locations in code you have to apply changes, and even more important, where not.

So, whenever you come to a function you don't understand because the function does "too much", and you are not sure if and where to apply a change, then consider to refactor the function into separate, smaller functions. Don't wait until you have to change something. Code is 10x more often read than changed, and smaller functions are much easier to read. To my experience, when a function has a certain complexity, you can always split the the function into different responsibilities, independent of knowing which changes will come in the future. Bob Martin typically goes a step further, see the link I gave in my comments below.

EDIT: to your comment: The main responsibility of the outer function in the example above is not to print to a specific device, or to format the document - it is to integrate the printing workflow. Thus, at the abstraction level of the outer function, a new requirement like "docs should not be formatted anymore" or "doc should be mailed instead of printed" is just "the same reason" - namely "printing workflow has changed". If we talk about things like that, it is important to stick to the right level of abstraction.


答:
I think you're misunderstanding SRP.

The single reason for change is NOT about changing the code but about what your code does.

Title: Can/should the Single Responsibility Principle be applied to new code?

Body:
The principle is defined as modules having one reason to change. My question is, surely these reasons to change are not known until the code actually starts to change?? Pretty much every piece of code has numerous reasons why it could possibly change but surely attempting to anticipate all of these and design your code with this in mind would end up with very poor code. Isn't it a better idea to only really start to apply SRP when requests to change the code start coming in? More specifically, when a piece of code has changed more than once for more than one reason, thus proving it has more than one reason to change. It sounds very anti-Agile to attempt to guess reasons for change.

An example would be a piece of code which prints a document. A request comes in to change it to print to PDF and then a second request is made to change it to apply some different formatting to the document. At this point you have proof of more than a single reason to change (and violation of SRP) and should make the appropriate refactoring.


答:
When you are designing a new system, it is wise to consider the kind of changes you may have to make during its lifetime and how expensive those will be given the architecture you are putting into place.
Splitting your system into modules is an expensive decision to get wrong.

A good source of information is the mental model in the head of the business' domain experts. Take the example of the document, the formatting, and the pdf. The domain experts will likely tell you they format their letters using document templates. Either on stationary or in Word or whatever. You can retrieve this information before you start coding and use it in your design.

A great read about these things: Lean Architecture by Coplien


问:
Unique Value Object vs Entity
Trying to convert some entities into value objects I am stuck in a case where what seems a value object must be unique within an aggregate.

Suppose we have a Movie entity which makes the root of an aggregate. This Movie entity is related with some set of AdvertisementEvent objects with the role of displaying an advertisement at certain timestamp.

The AdvertisementEvent contains a link to some Banner that must be displayed, the coordinates and some effect filters.

Since AdvertisementEvent is just a collection of configuration parameters I am not sure if I should care about its identity and treat it like just a large value object. However I do care that within a Movie there must be only one AdvertisementEvent at a certain timestamp, probably even around the timestamps.

I find hard to split my doubts in multiple independent questions, so there they go:

Does a collection of configuration parameters sounds like a value object?

Am I mixing the concept of uniqueness of AdvertisementEvent within Movie and  transactional integrity rule?

Does any of the choices in point (2) implies that AdvertisementEvent must be a member of the aggregate made by Movie?

Is my AdvertisementEvent object an Entity, a Value Object or an Event Object? (I used the Event suffix in the name to highlight my confusion)

Are large value objects like this a design smell?

I guess that I am not dealing with an Event in the sense of DDD because it is not something that just happens. The real DDD event should be something more like AdvertisementEventReached

答:
The distinction between Entity and Value object should be based around the question: If I have two objects with the same contents (two AdvertisementEvents linking to the same Banner with the same parameters), should I treat them differently or can one be replaced by the other without affecting how the software works?

In this case, I would say that you can replace one AdvertisementEvent by another with the same values without affecting the operation of the software. This makes them Value objects (the contained value is what counts, not the identity of the object itself).

As for the size of a Value object: As long as it contains a coherent set of parameters for a single responsibility, there is no limit on how large a Value object can be. In the implementation it might be good to pay special attention to large value objects to ensure they are not needlessly and excessively copied but otherwise it is no problem.

As for the constraints on the number of AdvertisementEvents you have within a Movie, this is a constraint on the relation between a Movie and its collection of AdvertisementEvents, not on one of those classes individually. As such, the most logical place to enforce the constrained is at the point where the collection gets maintained in Movie (thus in the method where you try to add an AdvertisementEvent).

Title: Unique Value Object vs Entity


答:
A reason for change is, ultimately, a change in specification or information about environment where the application runs. So a single responsibility principle is telling you to write each component (class, function, module, service ...) so that it needs to consider as little of the specification and of the execution environment as possible.

Since you know the specification and environment when you write the component, you can apply the principle.

If you consider the example of code that prints a document. You should consider whether you can define the layout template without considering the document will end up in PDF. You can, so SRP is telling you you should.

Of course YAGNI is telling you you shouldn't. You need to find balance between the design principles.