I would not give it to a beginner as it would corrupt their mind with useless drivel .
It's authors exhibit themselves as morons who celebrate renaming existing computer science concepts while occasionally mixing and matching them.
I would not be this uncharitable towards it if it was not such a famous (and hence harmfull) book.
It's harmfull because software engineering is really hard, and they just add up to the load by trying to have the reader memoize their junk instead of doing something that would actually make them a better programmer. And, if you try to use their concepts while programming - shudders, oh god help you.
I'm not going to iterate over every pattern. Here's an example:
Flywheight? You assholes, just tell memoization for what it is. Why don't you rename existing data structures as well? Good thing those come out of the box, otherwise you would have began the book by renaming array, linked list and dictionary. Maybe you would have called linked list "the chaingang" or something.
You don't simplify things by giving things cuddlier names. You stunt peoples growth that way.
Gang of four book is a malignant offshoot of the practice of attempting to make software engineering better by legalizing and dogmatizing it by decomposition into trivial details that hurt your brain. It's a branch of 'consultancy driven software development' where people attempt to aquire a halo of professionalism by calling things by fancy names and over-complex descriptions (while skipping the practical things with equally complex names but at least those weren't made up by a bunch of idiots).
Among the few patterns that are more generally useful and have stood the test of time, we'd find Composite, Command and of course Observer.
What I understand from your comment is that you dislike the Gang of four book because it renames concepts that don't need the cutesy names that they give them. Do you have a problem with the _concept_ of design patterns? Or just the names they are given? Are the concepts themselves sound and worth paying attention to?
"It reads like it was written by a clever, verbose, and 'over-eager novice."
Design patterns are a really usefull concept. The GoF book just totally botches up that concept by dwelving deep in trivial language details while missing the big picture.
Christopher Alexander's "A timeless way of building", and "Notes on the Synthesis of Form" are the books in architecture that prompted a lot of dicussion in software design circles, and from which I presume GoF got their idea of software design patterns.
What are good design patterns in software? IMO they are composed from the programming models exposed in a basic CS book like Aho and Ullman's "Foundations of Computer Science" and further developed in a books like Structure And Intrepretation of Computer Programs.
GoF is an ok anecdotal reference after those, but it really is not suitable as a didactic resource.
Peter Norvig wryly commented that 16 of the 23 pattern are either invisible or non-existent in lisp Lisp[0].
[0] http://www.norvig.com/design-patterns/design-patterns.pdf
Design Patterns are very useful, but they are a tool like anything else.
They're not just a bunch of things with cutesy names, they are the most common and core patterns that we can use in OO.
Yes, they are way overused, particularly in Java, but they are useful.
The book could be summarized however.
this level of the craft is subtle, intuitive, and often inaccessible to the conscious intellect.
Patterns can be useful but only in moderation and only with reason. They're spice.
A contrived example, but:
https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
FizzBuzz Enterprise Edition. It's enterprisey!
Any advice to deal with this kind of people would be much appreciated. I had a hard time trying to convey basic software engineering practices such as not hard-coding file paths, using version control instead of filenames to manage versions, removing dead code, keeping the code at least moderately DRY, more or less sticking to a code convention, etc. They would use all their reasoning power to refute what they would see as meaningless pet-peeves. It was tiring. I tried to provide pointers so they could find out for themselves but they gave it zero interest. At the moment I've given up.
The simple fact the OP is asking this question here means she or he will almost certainly do greatly.
More in general, the problem is that these people have been in an environment where programs were small enough that those practices didn't cause problems. They've moved into an environment where the scale is different, and those practices now cause real pain. Until they experience the pain (rather than just being told about it), they aren't really going to get it.
If you do
* 100% pairing,
* buttloads of unit tests,
* lots of microservices,
* use an autoformatter,
* in a Node codebase,
to order-of-magnitude approximations you're probably going to be about as effective a team as if you
* always code alone,
* mostly write integration tests,
* write a big old monolith,
* mostly ignore code style (except for egregious cases),
* in C.
These variables do make a difference, but those differences are context-dependent and can be swamped by other factors. Use version control. Do at least some testing and some code review. Make sure engineers can actually run their code before submitting it (on their laptops or in special staging environments or whatever, it doesn't matter much.) Help coworkers when they're stuck, and ask for help when you're stuck. And try to hire Harrison Bergeron onto your team :-).
In code bases you have written yourself, often you remember enough about it that you can mitigate the effects of complexity. Possibly you already had a plan for how to implement some functionality. Or maybe you know how to avoid certain problems.
As programs become more complex, you will find that "legacy team members" are disproportionately productive. Learning the code base becomes more important than learning the problem domain.
Teams that expend effort on maintaining a status quo where the exploring the problem domain dominates the cost of development (even with new developers), will usually lag behind teams that do not. Mostly, because it is difficult to do.
Some of the practices you mention can be used to help in this, but for a "legacy team member" it might not be attractive. If you have a more typical situation, knowing the code base better means you are much more productive and therefore more valuable. This secures a senior position on the team. Turnover is usually high, so most people leave before it gets to the point where even "legacy team members" become unproductive. When you go to a new shop, you can always complain about the "crappy" code and suggest a complete rewrite (at which point, you secure your senior status again).
While your list does not necessarily comprise what I think of a "productive practices", I think it is incorrect to imply that "productive practices" can not have a profound impact on the outcome of a project. The productive practices that work best for each team will likely be different. It's important to pick practices that work for your team and produce code that is simple to read and extend. Not thinking about it is a good way to ensure that you will end up with a complex system.
On a related note, I just this week stumbled upon a post / essay, which was probably the best piece of writing I've read in computer-aided engineering, and working in a disciplined manner. I'd recommend reading it right now, as the very first thing you do: https://queue.acm.org/detail.cfm?id=3197520
What? Those are unnecessary details as far as software engineering is concerned.
To this list, I would also suggest compiler construction or database systems as different topics exhibiting the same thing.
A more basic challenge for a scientific programmer might be absorbing the mindset of tool building rather than problem solving. It's a different mental perspective to think of your code as a product for other developers rather than as a means to producing a data artifact.
What I like about them are that they describe large complex systems that have to work with a bunch of people plugging in their own implementation of the parts. For me, both books give a good sense of what you need to do to enable the product you are working on to evolve successfully, and highlight areas where a lack of flexibility impacted that evolution.
So often in programming you look at your code and have to evaluate not only what features you are delivering but also what paths you are closing off with your design. In my experience the folks who excel at programming hold both the model of the system in their mind while they execute some part of it.
I think both books give a flavor of that.
My observation is that you're halfway there when you realize that you need to improve, of the folks I saw who did poorly it was because they didn't realize that you could be both the smartest person in the room and the least capable at the same time.
Right now, on your first job experience, even a kid who never went to college is better at programming than you are because they've been experiencing all the pitfalls that can happen and have built up a knowledge from that which is perhaps more intuitive than formal but serves them well. What you have over that person is that you've trained yourself to consume, classify, organize, and distill massive amounts of information in a short amount of time.
Use that training to consume everything you can on the art of writing programs. Read "Test Driven Development" read "Code Complete", read "Design Patterns", read "The Design of the UNIX Operating System", read "TCP/IP Illustrated Volume 1", and a book or two on databases. With your training you should be able to skim through those to identify the various "tricky bits" and get a feel for what is and what is not important in this new field of yours.
Soak in as much as you can and ask a lot of questions. Pretty soon no one will know you haven't been doing this your whole life.