Code Complete: A Practical Handbook of Software Construction, Second Edition

Author: Steve McConnell
4.6
All Stack Overflow 109
This Year Stack Overflow 6
This Month Hacker News 1

Code Complete: A Practical Handbook of Software Construction, Second Edition

4.6

Review Date:

Comments

by fdsvnsmvas   2018-09-13
Thanks everyone, the comments are much appreciated. Here's a list of books and other media resources recommended so far in the thread:

Robert C. Martin, Clean code: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsma...

Vaughn Vernon, various: https://www.amazon.com/Code-Complete-Practical-Handbook-Cons... 2

Clean coder: https://www.amazon.com/Pragmatic-Programmer-Journeyman-Maste...

Hitchhiker's Guide to Python: https://www.amazon.com/Art-Readable-Code-Practical-Technique...

John Ousterhout, A Philosophy of Software Design: https://www.amazon.com/Philosophy-Software-Design-John-Ouste... This one looks particularly interesting, thanks AlexCoventry!

Kent Beck, Test Driven Development: https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/...

Dan Bader, Python Tricks: The Book: https://www.amazon.com/Software-Engineering-10th-Ian-Sommerv...

Svilen Dobrev, various: http://www.svilendobrev.com/rabota/

by anonymous   2018-03-19

You cannot set the default values for your enum members, only for whole enum. Default value for it is 0, which goes to first element of enum. Other enum members should differ from that value, otherwise they simply override it. In this case:

enum Foo { Bar=0, Baz=0, bread=0, jam=0 };

You're saying to compiler: OK, now they 0 will be named as Bar. Ok, now 0 will be named as Baz, and so on. It doesn't make any sence for compiler.

In a book Code Complete one can find an advice to introduce a default enum member named like None and explicitly assign it to 0 and place it at first place of your enum. So, your code could looks like this:

enum Foo
{
    None = 0,
    Bar, // 1
    Baz, // 2
    bread, // 3
    jam // 4
};
by anonymous   2018-03-19

You should use the file option to initialize the photo image object.
This means you need to change photo = PhotoImage("eh.gif") to photo = PhotoImage(file="eh.gif")

Now your code will work. But a working code is not necessarily a good code. There are other issues with your code. Let me go through them quickly:

  • It is better to code import Tkinter as Tk than from Tkinter import *
  • Why that hyphen in your class name? Follow PEP8 so that, in the futur, people will find it easy to review and understand your code.
  • Good that you have written self.master = master (read complete code to know why) but then you have never used it. This means you made a good decision and you render it useless.
  • You set the title of the window within the initializer. It is better if you do that in a separate function so that whenever you want to add additional settings to your GUI (such as the size, font or whatever) you will only add code to that function instead of vomiting lot of trash inside the initializer which rather needs to be clean.
  • None of the widgets you created is 'selfed' (you may read Why explicit self has to stay)
  • It is better you create the widgets in a separate function otherwise your __init__() will be dirty.
  • Why do you use return in prank() and close_window()? By default, Python functions that do not return something return None anyway so it is useless to code that.
  • Why did you pack one button to left and the other one to right and then no pack siding for the label? Read about the pack() geometry manager.
  • Why you did not attach the label to a parent widget as you did for the 2 other buttons? All Tkinter widgets need to be clung into a parent widget. The grand parent of those widgets is an instance of Tkinter.Tk()
  • Why did you create that frame and then you never used it? You are not doing anything with it, so ..?

Given these remarks, I want to provide you an improved -but not perfect- version of your program. You can then follow this 'philosophy' to add or modifying existing widgets:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import Tkinter as Tk
from PIL import ImageTk

class FakeVirus:
   def __init__(self, master):
       self.master = master
       self.configure_gui()
       self.create_widgets()

   def configure_gui(self):
       self.master.title('Totally not a virus!')

   def create_widgets(self):
       self.create_buttons()
       self.create_label_for_image()

   def create_buttons(self):
       self.help = Tk.Button(self.master, text='Help', command=self.prank)
       self.help.pack(side=Tk.LEFT)
       self.quit = Tk.Button(self.master, text='Close', command=self.close_window)
       self.quit.pack(side=Tk.LEFT)

   def create_label_for_image(self):
       self.image_label = Tk.Label(self.master)
       self.image_label.pack(side=Tk.LEFT)
       self.load_image_to_label()

   def load_image_to_label(self):
       self.photo = ImageTk.PhotoImage(file='eh.gif')
       self.image_label.image = self.photo
       self.image_label.config(image=self.photo)

   def prank(self):
       print "work"

   def close_window(self):
        root.destroy()

if __name__ == '__main__':
   root = Tk.Tk()
   my_gui = FakeVirus(root)
   root.mainloop()

The output of the above program is:

enter image description here

by anonymous   2018-03-19

The build is deterministic, is the result of running VS builder or MSBuild on the solution file and the project files. They define strictly what assemblies are produced, there is no flexibility there. The general rule is "one .csproj file produces one assembly". And one .cs file belongs to one .csproj.

As for you modifying the access of a method or type to internal and then discovering at runtime that something is broken, you can rest assured: the discovery occurs at compile time. Your code won't even compile anymore.

Also, your binary 'may or may not work' seems like you're missing basic unit tests. Add unit tests, make them part of your build, and then you'll know if the code works or not (at least the part that is tested). Integration tests also help. Get started with developer testing tools.

Also, read Code Complete. So many of your questions were answered years ago and is sad to see them come back again and again.

by anonymous   2018-01-01

You don't need var before variables here

function doGetWord(){
            var word = F.gword.value;
            var wLength = word.length;

As the idea is to save this values in scope of parent function. And you might replace the letters like this

const letters = document.getElementById("dword").textContent.split('');
letters[i] = dummy;
document.getElementById("dword").textContent = letters.join('');

You are using bad variable names and a lot of global variables, it might be a good practice to work of this. I recommend reading a book on general programming, something like https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670 and something more specific to javascript (to get the concept of scopes) https://www.manning.com/books/secrets-of-the-javascript-ninja

    <!DOCTYPE html>
    <html>

      <head>
        <title>Story</title>
        <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <style>
            /*body {
                font-family: Calibri;
                font-size: 13.5pt;
                margin-left: 5px;
                color: black;
            }*/

            #aa{
                border: 1px solid black;
            }

            /*.in2{
                width: 300px;
                height: 630px;
                border: 0px solid white;
                background-color: white;
                color: white;
                font-family: Arial;
                font-size: 25pt;
            }*/
        </style>
        <script src="jquery-3.2.1.js"></script>
        <script type="text/javascript">
            var word = "" //word variable
            var wLength = 0 //word length variable
            var dummy = "" //letter guessed
            var dm = new Array(26)


            $(document).ready(function(){
                $("input.in2").hide()
            })

            $(document).ready(function(){
                $("input.bi2").hide()
            })

            function doGetWord(){
                word = F.gword.value;
                wLength = word.length;
                for(var i = 0; i < wLength; i++){
                    document.getElementById("dword").innerHTML += "_ "
                }
                $("input.wordi").hide()
                $("input.bi").hide()
                $("input.in2").show()
                $("input.bi2").show()
            }

            function doGuess(){
                dummy = F.t.value
                if(dummy.length > 1){
                    dummy = ""
                    F.t.value = ""
                }
                else{
                    F.t.value = ""
                    alp = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
                    dd = dummy.toString()
                    window["cl" + dd]
                    if(window["cl" + dd] == false){
                        alert("Letter already used, please try again with another letter")
                        dummy = ""
                        F.t.value = ""
                    }
                    else{
                        window["cl" + dd] = false
                        F.t.value = ""
                        doGuessWord();
                    }
                }
            }

            function doGuessWord(){
                const letters = document.getElementById("dword").textContent.split(' ');
                for(i = 0; i < wLength; i++){
                    if(dummy === word.charAt(i)) {
                        letters[i] = dummy;
                    }
                }
                document.getElementById("dword").textContent = letters.join(' ');
            }
        </script>
      </head>

      <body>
        <form name="F">
          <input type="text" name="gword" class="wordi" />
          <input type="text" name="t" class="in2" />
          <input type="button" name="b" value="do" onclick="doGetWord()" class="bi" />
          <input type="button" name="b2" value="do" onclick="doGuess()" class="bi2" />
          <div id="dword"></div>
        </form>
      </body>

    </html>

by anonymous   2017-08-20

For decades programmers have often spent time making software worse by applying practices they don't understand, rather than learning why that practice is good. The use of certain tools/keywords/frameworkes can make a programmer feel sophisticated, when they're just screwing things up. Some common examples:

  • Throwing in lots of try/catch/finally blocks can make a programmer feel like they have an error handling scheme, when in fact they don't.
  • Replacing sql with stored procedures can make programmers feel like they have a data access layer that magically gives them efficiency, reuseability, encapsulation, when in fact they don't.
  • Using classes makes many programmers believe they're engaging in object oriented programming, when in fact they aren't (or are only scratching the surface of OO).

This list could go on forever. This tendency has always been around and always will be, because we humans always look for shortcuts. We see this a lot with patterns now because patterns are currently popular. The root problem is the same: developers not having a respect for how complicated software development is, and thinking a blindly implemented pattern or practice is a substitute for learning and humility.

The solution? Difficult to say. You can't go to wrong though handing a junior developer Code Complete or some such, to help them understand this is all about applying principles to particular situations, and that great developers keep it simple.

by Yuval F   2017-08-20

For decision tables, please see my answer to this question, or better still read chapter 18 in Code Complete 2.

by anonymous   2017-08-20

You might wnat to check out The Definitive C++ Book Guide and List

For your purposes I would especially recommend:

They are not in particular order, also you might want to read and code something in between them.

(Note: As noted by @John Dibling the Boost book might be a bit out of date, I do not have experience with that one myself)

by anonymous   2017-08-20

I'm going to go out on a limb here and suggest that you write some code.

Read Code Complete. Look at other questions about this topic here at StackOverflow. Find an open source project and contribute to it. Start your own pet project that focuses on the skills you're interested in.

When to use Design patterns
How to get into C# Open Source projects