07 December 2007

🏗️Software Engineering: Software (Just the Quotes)

"Since software construction is inherently a systems effort - an exercise in complex interrelationships - communication effort is great, and it quickly dominates the decrease in individual task time brought about by partitioning [increasing the workers]. Adding more people then lengthens, not shortens, the schedule." (Frederick Brook, "The Mythical Man-Month", 1975)

"The fundamental problem with software maintenance is that fixing a defect has a substantial (20-50 percent) chance of introducing another. So the whole process is two steps forward and one step back. Why aren't defects fixed more cleanly? First, even a subtle defect shows itself as a local failure of some kind. In fact it often has system-wide ramifications, usually nonobvious. Any attempt to fix it with minimum effort will repair the local and obvious, but unless the structure is pure or the documentation very fine, the far-reaching effects of the repair will be overlooked. Second, the repairer is usually not the man who wrote the code, and often he is a junior programmer or trainee. (Frederick P. Brooks, "The Mythical Man-Month" , 1975)

"The hardest single part of building a software system is deciding precisely what to build." (Frederick P. Brooks, "The Mythical Man-Month", 1975) 

"The essence of a software entity is a construct of interlocking concepts: […] I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation." (Fred Brooks, "No Silver Bullet", 1986)

"The finest pieces of software are those where one individual has a complete sense of exactly how the program works. To have that, you have to really love the program and concentrate on keeping it simple, to an incredible degree." (Bill Gates , [interview], 1986)

"There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies." (Charles A R Hoare, [lecture] 1987)

"Object-oriented programming languages support encapsulation, thereby improving the ability of software to be reused, refined, tested, maintained, and extended. The full benefit of this support can only be realized if encapsulation is maximized during the design process. […] design practices which take a data-driven approach fail to maximize encapsulation because they focus too quickly on the implementation of objects." (Rebecca Wirfs-Brock, "Object-oriented Design: A. responsibility-driven approach", 1989)

"Programmers are responsible for software quality - quality in their own work, quality in the products that incorporate their work, and quality at the interfaces between components. Quality has never been and will never be tested in. The responsibility is both moral and professional." (Boris Beizer, "Software Testing Techniques", 1990)

"The complexity barrier. Software complexity (and therefore that of bugs) grows to the limits of our ability to manage that complexity." (Boris Beizer, "Software Testing Techniques", 1990)

"The most common kind of coding bug, and often considered the least harmful, are documentation bugs (i.e., erroneous comments). Although many documentation bugs are simple spelling errors or the result of poor writing, many are actual errors - that is, misleading or erroneous comments. We can no longer afford to discount such bugs, because their consequences are as great as 'true' coding errors. Today programming labor is dominated by maintenance. This will increase as software becomes even longer-lived. Documentation bugs lead to incorrect maintenance actions and therefore cause the insertion of other bugs." (Boris Beizer, "Software Testing Techniques", 1990)

"Every software system needs to have a simple yet powerful organizational philosophy (think of it as the software equivalent of a sound bite that describes the system's architecture). [A] step in [the] development process is to articulate this architectural framework, so that we might have a stable foundation upon which to evolve the system's function points." (Grady Booch, "Object-Oriented Design: with Applications", 1991)

"The fundamentals of language are not understood to this day. [...] Until we understand languages of communication involving humans as they are then it is unlikely many of our software problems will vanish." (Richard W Hamming, "The Art of Probability for Scientists and Engineers", 1991)

"As the size of software systems increases, the algorithms and data structures of the computation no longer constitute the major design problems. When systems are constructed from many components, the organization of the overall system - the software architecture - presents a new set of design problems. This level of design has been addressed in a number of ways including informal diagrams and descriptive terms, module interconnection languages, templates and frameworks for systems that serve the needs of specific domains, and formal models of component integration mechanisms." (David Garlan & Mary Shaw, "An introduction to software architecture", Advances in software engineering and knowledge engineering Vol 1, 1993)

"Testing by itself does not improve software quality. Test results are an indicator of quality, but in and of themselves, they don't improve it. Trying to improve software quality by increasing the amount of testing is like trying to lose weight by weighing yourself more often. What you eat before you step onto the scale determines how much you will weigh, and the software development techniques you use determine how many errors testing will find. If you want to lose weight, don't buy a new scale; change your diet. If you want to improve your software, don't test more; develop better." (Steve C McConnell, "Code Complete: A Practical Handbook of Software Construction", 1993)

"Software architecture involves the description of elements from which systems are built, interactions among those elements, patterns that guide their composition, and constraints on these patterns. In general, a particular system is defined in terms of a collection of components and interactions among those components. Such a system may in turn be used as a (composite) element in a larger system design." (Mary Shaw & David Garlan,"Characteristics of Higher-Level Languages for Software Architecture", 1994)

"Our experience with designing and analyzing large and complex software-intensive systems has led us to recognize the role of business and organization in the design of the system and in its ultimate success or failure. Systems are built to satisfy an organization's requirements (or assumed requirements in the case of shrink-wrapped products). These requirements dictate the system's performance, availability, security, compatibility with other systems, and the ability to accommodate change over its lifetime. The desire to satisfy these goals with software that has the requisite properties influences the design choices made by a software architect." (Len Bass et al, "Software Architecture in Practice", 1998)

"Generically, an architecture is the description of the set of components and the relationships between them. […] A software architecture describes the layout of the software modules and the connections and relationships among them. A hardware architecture can describe how the hardware components are organized. However, both these definitions can apply to a single computer, a single information system, or a family of information systems. Thus 'architecture' can have a range of meanings, goals, and abstraction levels, depending on who’s speaking." (Frank J Armour et al, "A big-picture look at enterprise architectures", IT professional Vol 1 (1), 1999)

"Planning is not about predicting the future. When you make a plan for developing a piece of software, development is not going to go like that. Not ever. Your customers wouldn’t even be happy if it did, because by the time software gets there, the customers don’t want what was planned, they want something different." (Kent Beck & Martin Fowler, "Planning Extreme Programming", 2000)

"Design patterns provide the cores of ready-made solutions that can be used to solve many of software’s most common problems. Some software problems require solutions that are derived from first principles. But most problems are similar to past problems, and those can be solved using similar solutions, or patterns." (Steve C McConnell, "Code Complete: A Practical Handbook of Software Construction" 2nd Ed., 2004)

"The software architecture of a system or a family of systems has one of the most significant impacts on the quality of an organization's enterprise architecture. While the design of software systems concentrates on satisfying the functional requirements for a system, the design of the software architecture for systems concentrates on the nonfunctional or quality requirements for systems. These quality requirements are concerns at the enterprise level. The better an organization specifies and characterizes the software architecture for its systems, the better it can characterize and manage its enterprise architecture. By explicitly defining the systems software architectures, an organization will be better able to reflect the priorities and trade-offs that are important to the organization in the software that it builds." (James McGovern et al, "A Practical Guide to Enterprise Architecture", 2004)

"A road plan can show the exact location, elevation, and dimensions of any part of the structure. The map corresponds to the structure, but it's not the same as the structure. Software, on the other hand, is just a codification of the behaviors that the programmers and users want to take place. The map is the same as the structure. […] This means that software can only be described accurately at the level of individual instructions. […] A map or a blueprint for a piece of software must greatly simplify the representation in order to be comprehensible. But by doing so, it becomes inaccurate and ultimately incorrect. This is an important realization: any architecture, design, or diagram we create for software is essentially inadequate. If we represent every detail, then we're merely duplicating the software in another form, and we're wasting our time and effort." (George Stepanek, "Software Project Secrets: Why Software Projects Fail", 2005)

"Software is abstract and therefore seems as if it should be infinitely malleable. And yet, for all its ethereal flexibility, it can be stubbornly, maddeningly intractable, and it is constantly surprising us with its rigidity." (Scott Rosenberg, "Dreaming in Code", 2007)

"Software is different; it has no core. It is onionlike, a thing of layers, each built painstakingly and precariously on the previous one, each counting on the one below not to move or change too much. Software builders like to talk about laying bricks; skeptics see a house of cards. Either way, there’s a steady accumulation going on. New layers pile on old. Programmers call these accretions 'layers of abstraction', because each time a new one is added, something complex and specific is being translated into something simpler and more general." (Scott Rosenberg, "Dreaming in Code", 2007)

"Software is easy to make, except when you want it to do something new. And then, of course, there is a corollary: The only software that's worth making is software that does something new." (Scott Rosenberg, "Dreaming in Code", 2007)

"The names programmers adopt for their abstractions are, as geeks like to say, 'nontrivial'. In software, labels and names matter; they are the handles by which you grab things." (Scott Rosenberg, "Dreaming in Code", 2007)

"There is almost always something you can pull off the shelf that will satisfy many of your needs. But usually the parts of what you need done that your off-the-shelf code won’t handle are the very parts that make your new project different, unique, innovative - and they’re why you’re building it in the first place." (Scott Rosenberg, "Dreaming in Code", 2007)

"We tend to form mental models that are simpler than reality; so if we create represented models that are simpler than the actual implementation model, we help the user achieve a better understanding. […] Understanding how software actually works always helps someone to use it, but this understanding usually comes at a significant cost. One of the most significant ways in which computers can assist human beings is by putting a simple face on complex processes and situations. As a result, user interfaces that are consistent with users’ mental models are vastly superior to those that are merely reflections of the implementation model." (Alan Cooper et al,  "About Face 3: The Essentials of Interaction Design", 2007)

"Part of the beauty of software is that it’s deterministic - the computer does exactly what you tell it to do, and, given the same starting point, it will do exactly the same thing every time." (Paul Butcher, "Debug It! Find, Repair, and Prevent Bugs in Your Code", 2009)

"Writing and (particularly) maintaining software is a continual battle against entropy. Keeping on top of quality is tough, requiring high levels of discipline. This discipline is difficult enough to maintain under the best of circumstances, let alone when faced with concrete evidence that the software is uncared for, such as a long-unfixed bug. As soon as discipline slips, quality can go into a self-reinforcing downward spiral, and you’re in real trouble." (Paul Butcher, "Debug It! Find, Repair, and Prevent Bugs in Your Code", 2009)

"We developers can easily develop blind spots. We necessarily have a different perspective from our users, and that can mean we miss important information that would be obvious to someone who understands things from their point of view. Furthermore, our focus tends to be on working out how to make the software work, not proving that it’s broken." (Paul Butcher, "Debug It! Find, Repair, and Prevent Bugs in Your Code", 2009)

"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written." (Jay Fields et al, "Refactoring: Ruby Edition", 2010)

"An obsession with 'feature delivery' ignores the human-related and team-related dynamics inherent in modern software, leading to a lack of engagement from staff, especially when the cognitive load is exceeded." (Matthew Skelton, "Team Topologies: Organizing Business and Technology Teams for Fast Flow", 2019)

"Trying to determine the cognitive load of software using simple measures such as lines of code, number of modules, classes, or methods is misguided. […] When measuring cognitive load, what we really care about is the domain complexity - how complex is the problem that we’re trying to solve with software? A domain is a more largely applicable concept than software size." (Matthew Skelton, "Team Topologies: Organizing Business and Technology Teams for Fast Flow", 2019)

"One of the great enemies of design is when systems or objects become more complex than a person - or even a team of people - can keep in their heads. This is why software is generally beneath contempt." (Bran Ferren)

"The thing that makes software design difficult is that we must express thoughts about a problem and a solution we typically do not understand fully, using a language that does not contain many of our accustomed features of expression, to a system that is unforgiving of mistakes." (Alistair Cockburn)

06 December 2007

🏗️Software Engineering: Algorithms (Just the Quotes)

"Design problems - generating or discovering alternatives - are complex largely because they involve two spaces, an action space and a state space, that generally have completely different structures. To find a design requires mapping the former of these on the latter. For many, if not most, design problems in the real world systematic algorithms are not known that guarantee solutions with reasonable amounts of computing effort. Design uses a wide range of heuristic devices - like means-end analysis, satisficing, and the other procedures that have been outlined - that have been found by experience to enhance the efficiency of search. Much remains to be learned about the nature and effectiveness of these devices." (Herbert A Simon, "The Logic of Heuristic Decision Making", [in "The Logic of Decision and Action"], 1966)

"Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures." (Rob Pike, "Notes on Programming in C" , 1989)

"Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming." (Rob Pike, "Notes on Programming in C", 1989)

"Apart from power laws, iteration is one of the prime sources of self-similarity. Iteration here means the repeated application of some rule or operation - doing the same thing over and over again. [...] A concept closely related to iteration is recursion. In an age of increasing automation and computation, many processes and calculations are recursive, and if a recursive algorithm is in fact repetitious, self-similarity is waiting in the wings.(Manfred Schroeder, "Fractals, Chaos, Power Laws Minutes from an Infinite Paradise", 1990)

"An algorithm gives you the instructions directly. A heuristic tells you how to discover the instructions for yourself, or at least where to look for them." (Steve McConnell, "Code Complete", 1993)

"As the size of software systems increases, the algorithms and data structures of the computation no longer constitute the major design problems. When systems are constructed from many components, the organization of the overall system - the software architecture - presents a new set of design problems. This level of design has been addressed in a number of ways including informal diagrams and descriptive terms, module interconnection languages, templates and frameworks for systems that serve the needs of specific domains, and formal models of component integration mechanisms." (David Garlan & Mary Shaw, "An introduction to software architecture", Advances in software engineering and knowledge engineering Vol 1, 1993)

"From time to time, a complex algorithm will lead to a longer routine, and in those circumstances, the routine should be allowed to grow organically up to 100-200 lines. (A line is a noncomment, nonblank line of source code.) Decades of evidence say that routines of such length are no more error prone than shorter routines. Let issues such as the routine's cohesion, depth of nesting, number of variables, number of decision points, number of comments needed to explain the routine, and other complexity-related considerations dictate the length of the routine rather than imposing a length restriction per se." (Steve C McConnell," Code Complete: A Practical Handbook of Software Construction", 1993)

"Heuristic methods may aim at local optimization rather than at global optimization, that is, the algorithm optimizes the solution stepwise, finding the best solution at each small step of the solution process and 'hoping' that the global solution, which comprises the local ones, would be satisfactory." (Nikola K Kasabov, "Foundations of Neural Networks, Fuzzy Systems, and Knowledge Engineering", 1996)

"We all strive for simple and clear design, don't we? Of course we do. But in XP, we take it to extremes. At every moment in time, we want  the system to be as simple as possible. That means that we want no  additional functions that aren't used, no structures or algorithms that  are more complex than the current need would dictate." (Ron Jeffries, "Extreme Programming Installed", 2001)

"One of the essential parts of a formal training in programming is a long and demanding study of the large collection of algorithms that have already been discovered and analyzed, together with the Data Structures" (carefully tailored, seemingly unnatural ways of organizing data for effective access) that go with them. As with any other engineering profession, it is impossible to do a good job without a thorough knowledge of what has been tried before. If a programmer starts the job fully armed with what is already known, they will have some chance of finding something new. Inventiveness is important: not all problems have been seen before. A programmer who does not already know the standard algorithms and data structures is doomed to nothing more than rediscovering the basics." (Robert Plant & Stephen Murrell, "An Executive's Guide to Information Technology: Principles, Business Models, and Terminology", 2007)

"I find OOP methodologically wrong. It starts with classes. It is as if mathematicians would start with axioms. You do not start with axioms - you start with proofs. Only when you have found a bunch of related proofs, can you come up with axioms. You end with axioms. The same thing is true in programming: you have to start with interesting algorithms. Only when you understand them well, can you come up with an interface that will let them work." (Alexander Stepanov, [Interview with A. Stepanov] 2008)

"A second class of metaphors - mathematical algorithms, heuristics, and models - brings us closer to the world of computer science programs, simulations, and approximations of the brain and its cognitive processes." (Diego Rasskin-Gutman, "Chess Metaphors: Artificial Intelligence and the Human Mind", 2009)

"Making domain concepts explicit in your code means other programmers can gather the intent of the code much more easily than by trying to retrofit an algorithm into what they understand about a domain. It also means that when the domain model evolves - which it will, as your understanding of the domain grows - you are in a good position to evolve the code. Coupled with good encapsulation, the chances are good that the rule will exist in only one place, and that you can change it without any of the dependent code being any the wiser." (Dan North [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010]) 

"A software design pattern is a reusable solution to a reoccurring software design problem. […] A design pattern is not a concrete design or implementation, such as an algorithm that can be used as-is, but rather a gene." (Eddie Burris, "Programming in the Large with Design Patterns", 2012)

"Algorithm selection is often a design time decision but there are times when it is necessary or desirable to postpone algorithm selection until runtime. Runtime selection is preferable when the choice of algorithm depends on factors not available at design time. Such factors include: nature of input, source of input, user preferences and current conditions." (Eddie Burris, "Programming in the Large with Design Patterns", 2012)

"Programming is a science dressed up as art, because most of us don't understand the physics of software and it's rarely, if ever, taught. The physics of software is not algorithms, data structures, languages, and abstractions. These are just tools we make, use, and throw away. The real physics of software is the physics of people. Specifically, it's about our limitations when it comes to complexity and our desire to work together to solve large problems in pieces. This is the science of programming: make building blocks that people can understand and use easily, and people will work together to solve the very largest problems." (Pieter Hintjens, "ZeroMQ: Messaging for Many Applications", 2012)

"When you write a computer program you've got to not just list things out and sort of take an algorithm and translate it into a set of instructions. But when there's a bug - and all programs have bugs - you've got to debug it. You've got to go in, change it, and then re-execute - and you iterate. And that iteration is really a very, very good approximation of learning." (Nicholas Negroponte, "A 30-year history of the future", [Ted Talk] 2014)

"Programming is the process of taking an algorithm and encoding it into a notation that the computer can execute. These notation systems are referred to as programming languages. [...] Programming is an important part of what a computer scientist does. It is through programming that we create a representation of our solution. However, the solutions that we achieve are often affected by the process and language that we choose. [...] Programming languages must then provide a way to represent both the process and the data required by the solution." (Bradley N Miller et al, "Python Programming in Context", 2019)

05 December 2007

🏗️Software Engineering: Refactoring (Just the Quotes)

"When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous." (Kent Beck, "Refactoring: Improving the Design of Existing Code", 1999)

"When you find you have to add a feature to a program, and the program's code is not structured in a convenient way to add the feature, first refactor the program to make it easy to add the feature, then add the feature."  (Kent Beck, "Refactoring: Improving the Design of Existing Code", 1999)

"Unit tests can be tedious to write, but they save you time in the future (by catching bugs after changes). Less obviously, but just as important, is that they can save you time now: tests focus your design and implementation on simplicity, they support refactoring, and they validate features as you develop." (Ron Jeffries, "Extreme Programming Installed, 2001)

"Before you start refactoring, check that you have a solid suite of tests. These tests must be self-checking." (Martin Fowler et al, "Refactoring: Improving the Design of Existing Code", 2002)

"Given software engineers’ infatuation with indirection, it may not surprise you to learn that most refactoring introduces more indirection into a program. Refactoring tends to break big objects into several smaller ones and big methods into several smaller ones." (Kent Beck, "Indirection and Refactoring", 2002)

"One problem area for refactoring is databases. Most business applications are tightly coupled to the database schema that supports them. That's one reason that the database is difficult to change. Another reason is data migration. Even if you have carefully layered your system to minimize the dependencies between the database schema and the object model, changing the database schema forces you to migrate the data, which can be a long and fraught task." (Martin Fowler et al, "Refactoring: Improving the Design of Existing Code", 2002)

"Refactoring is risky. It requires changes to working code that can introduce subtle bugs. Refactoring, if not done properly, can set you back days, even weeks. And refactoring becomes riskier when practiced informally or ad hoc." (Erich Gamma, 2002)

"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written." (Martin Fowler et al, "Refactoring: Improving the Design of Existing Code", 2002)

"Refactoring is the process of taking a running program and adding to its value, not by changing its behavior but by giving it more of these qualities that enable us to continue developing at speed." (Kent Beck, "Why Refactoring Works", 2002)

"Refactoring changes the programs in small steps. If you make a mistake, it is easy to find the bug." (Martin Fowler et al, "Refactoring: Improving the Design of Existing Code", 2002)

"Without refactoring, the design of the program will decay. As people change code - changes to realize short-term goals or changes made without a full comprehension of the design of the code - the code loses its structure. It becomes harder to see the design by reading the code. Refactoring is rather like tidying up the code. Work is done to remove bits that aren't really in the right place. Loss of the structure of code has a cumulative effect. The harder it is to see the design in the code, the harder it is to preserve it, and the more rapidly it decays. Regular refactoring helps code retain its shape." (Martin Fowler et al, "Refactoring: Improving the Design of Existing Code", 2002)

"A commitment to simplicity of design means addressing the essence of design - the abstractions on which software is built - explicitly and up front. Abstractions are articulated, explained, reviewed and examined deeply, in isolation from the details of the implementation. This doesn’t imply a waterfall process, in which all design and specification precedes all coding. But developers who have experienced the benefits of this separation of concerns are reluctant to rush to code, because they know that an hour spent on designing abstractions can save days of refactoring." (Daniel Jackson, "Software Abstractions", 2006)

"To programmers, refactoring means rewriting a chunk of code to make it briefer, clearer, and easier to read without changing what it actually does. Refactoring is often compared to gardening; it is never finished." (Scott Rosenberg, "Dreaming in Code", 2007)

"It is a myth that we can get systems 'right the first time'. Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow. This is the essence of iterative and incremental agility. Test-driven development, refactoring, and the clean code they produce make this work at the code level." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"Refactoring is a lot like solving a Rubik’s cube. There are lots of little steps required to achieve a large goal. Each step enables the next." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"Refactoring is the process of improving the design of existing code without changing its behavior. [...] Bug fixing often uncovers opportunities for refactoring. The very fact that you’re working with code that contains a bug indicates that there is a chance that it could be clearer or better structured." (Paul Butcher, "Debug It! Find, Repair, and Prevent Bugs in Your Code", 2009)

"Although it is focused on the code, refactoring has a large impact on the design of a system. It is vital for senior designers and architects to understand the principles of refactoring and to use them in their projects." (Jay Fields et al, "Refactoring: Ruby Edition", 2010)

"Don’t be afraid of your code. Who cares if something gets temporarily broken while you move things around? A paralyzing fear of change is what got your project into this state to begin with. Investing the time to refactor will pay for itself several times over the lifecycle of your project. An added benefit is that your team’s experience dealing with the sick system makes you all experts in knowing how it should work. Apply this knowledge rather than resent it. Working on a system you hate is not how anybody should have to spend his time." (Mike Lewis, [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"New technology is an insufficient reason to refactor. One of the worst reasons to refactor is because the current code is way behind all the cool technology we have today, and we believe that a new language or framework can do things a lot more elegantly. Unless a cost-benefit analysis shows that a new language or framework will result in significant improvements in functionality, maintainability, or productivity, it is best to leave it as it is." (Rajith Attapattu [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written." (Jay Fields et al, "Refactoring: Ruby Edition", 2010)

"Technical debt is like a loan: you benefit from it in the short term, but you have to pay interest on it until it is fully paid off. Shortcuts in the code make it harder to add features or refactor your code. They are breeding grounds for defects and brittle test cases. The longer you leave it, the worse it gets." (Seb Rose [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010]) 

"What can you do to actually make your code tell the truth as clearly as possible? Strive for good names. Structure your code with respect to cohesive functionality, which also eases naming. Decouple your code to achieve orthogonality. Write automated tests explaining the intended behavior and check the interfaces. Refactor mercilessly when you learn how to code a simpler, better solution. Make your code as simple as possible to read and understand." (Peter Sommerlad, [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"When an engineer refactors the internals of a system without modifying its interface, whether for performance, clarity, or any other reason, the system’s tests shouldn’t need to change. The role of tests in this case is to ensure that the refactoring didn’t change the system’s behavior. Tests that need to be changed during a refactoring indicate that either the change is affecting the system’s behavior and isn’t a pure refactoring, or that the tests were not written at an appropriate level of abstraction." (Titus Winters, "Software Engineering at Google: Lessons Learned from Programming Over Time", 2020)

🏗️Software Engineering: Tools (Just the Quotes)

"This is generally true: any sizeable piece of program, or even a complete program package, is only a useful tool that can be used in a reliable fashion, provided that the documentation pertinent for the user is much shorter than the program text. If any machine or system requires a very thick manual, its usefulness becomes for that very circumstance subject to doubt!" (Edsger W. Dijkstra, "On the reliability of programs", 1970)

"Most programming languages are decidedly inferior to mathematical notation and are little used as tools of thought in ways that would be considered significant by, say, an applied mathematician." (Kenneth E Iverson, "Notation as a Tool of Thought", 1979)

"The properties of executability and universality associated with programming languages can be combined, in a single language, with the well-known properties of mathematical notation which make it such an effective tool of thought." (Kenneth E Iverson, "Notation as a Tool of Thought", 1979)

"Object-oriented programming increases the value of these metrics by managing this complexity. The most effective tool available for dealing with complexity is abstraction. Many types of abstraction can be used, but encapsulation is the main form of abstraction by which complexity is managed in object-oriented programming. Programming in an object-oriented language, however, does not ensure that the complexity of an application will be well encapsulated. Applying good programming techniques can improve encapsulation, but the full benefit of object-oriented programming can be realized only if encapsulation is a recognized goal of the design process." (Rebecca Wirfs-Brock," Object-Oriented Design: A responsibility-driven approach", 1989)

"Most programming tools and techniques focus on one aspect or a few related aspects of a system. The details of the aspect they select are shown in utmost clarity, but other details may be obscured or forgotten." (John Zachman, "Extending and Formalizing the Framework for Information Systems Architecture", 1992)

"An architecture framework is a tool which can be used for developing a broad range of different architectures [architecture descriptions]. It should describe a method for designing an information system in terms of a set of building blocks, and for showing how the building blocks fit together. It should contain a set of tools and provide a common vocabulary. It should also include a list of recommended standards and compliant products that can be used to implement the building blocks." (TOGAF, 2002)

"Executable UML is designed to produce a comprehensive and comprehensible model of a solution without making decisions about the organization of the software implementation. It is a highly abstract thinking tool to aid in the formalization of knowledge, a way of thinking about and describing the concepts that make up an abstract solution to a client problem." (Stephen J Mellor, "Executable UML: A Foundation for Model-Driven Architecture", 2002)

"Design patterns give names to practical knowledge; they define a high-level vocabulary for understanding and solving business statements graphically. Design patterns are presented in a standard format; they're like recipes in a cookbook or dress patterns in a catalog. Above all, they are practical, first as instructional materials and then as development tools." (Alan Chmura & J Mark Heumann, "Logical Data Modeling: What it is and How to do it", 2005)

"The amateur software engineer is always in search of magic, some sensational method or tool whose application promises to render software development trivial. It is the mark of the professional software engineer to know that no such panacea exist." (Grady Booch et al, "Object-Oriented Analysis and Design with Applications", 2007)

"Different tools may rely on different assumptions about their context - e.g., surrounding infrastructure, control model, data model, communication protocols, etc. - which can lead to an architectural mismatch between the application and the tools. Such a mismatch leads to hacks and workarounds that will make the code more complex than necessary." (Giovanni Asproni [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010]) 

"Conceptual models are best thought of as design-tools - a way for designers to straighten out and simplify the design and match it to the users’ task-domain, thereby making it clearer to users how they should think about the application. The designers’ responsibility is to devise a conceptual model that seems natural to users based on the users’ familiarity with the task domain. If designers do their job well, the conceptual model will be the basis for users’ mental models of the application." (Jeff Johnson & Austin Henderson, "Conceptual Models", 2011)

"Programming is a science dressed up as art, because most of us don’t understand the physics of software and it’s rarely, if ever, taught. The physics of software is not algorithms, data structures, languages, and abstractions. These are just tools we make, use, and throw away. The real physics of software is the physics of people. Specifically, it’s about our limitations when it comes to complexity and our desire to work together to solve large problems in pieces. This is the science of programming: make building blocks that people can understand and use easily, and people will work together to solve the very largest problems." (Pieter Hintjens, "ZeroMQ: Messaging for Many Applications", 2012)

"[…] building for scale that you don’t need is wasted effort and may lock you into an inflexible design. In effect, it is a form of premature optimization. However, it’s also important to choose the right tool for the job, and different technologies each have their own strengths and weaknesses." (Martin Kleppmann, "Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems", 2015)

"Language influences thought, tools influence action. Therefore, it matters a lot how we choose our tools. We shape our tooling and access landscape, and thereafter they shape the contours of our collaboration. When we choose a lot of different specialty tools, they in turn nudge us into different specialty groups." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"[…] when different types of specialists use common tools, techniques, and practices for similar activities, it creates a fertile common ground for cross-functional collaboration." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"When people use different tools for similar activities (e.g., version control, work tracking, documentation), they tend to form groups (camps) around tool usage boundaries. […] The more we are invested in certain tools, the greater the likelihood of deriving a part of our identity from the tool and its ecosystem." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"The intention behind prototypes is to explore the visualization design space, as opposed to the data space. A typical project usually entails a series of prototypes; each is a tool to gather feedback from stakeholders and help explore different ways to most effectively support the higher-level questions that they have. The repeated feedback also helps validate the operationalization along the way." (Danyel Fisher & Miriah Meyer, "Making Data Visual", 2018)

04 December 2007

🏗️Software Engineering: Software Development (Just the Quotes)

"Far be it from me to suggest that all changes in customer objectives and requirements must, can, or should be incorporated in the design. Clearly a threshold has to be established, and it must get higher and higher as development proceeds, or no product ever appears." (Fred P Brooks, "The Mythical Man-Month: Essays", 1975)

"Economic principles underlie the overall structure of the software lifecycle, and its primary refinements of prototyping, incremental development, and advancemanship. The primary economic driver of the life-cycle structure is the significantly increasing cost of making a software change or fixing a software problem, as a function of the phase in which the change or fix is made." (Barry Boehm, "Software Engineering Economics", 1981)

"Poor management can increase software costs more rapidly than any other factor. Particularly on large projects, each of the following mismanagement actions has often been responsible for doubling software development costs." (Barry Boehm, "Software Engineering Economics", 1981)

"The primary functions of a software process model are to determine the order of the stages involved in software development and evolution and to establish the transition criteria for progressing from one Stage to the next. These include completion criteria for the current stage plus choice criteria and entrance criteria for the next stage. Thus, a process model addresses the following software project questions: (1) What shall we do next? (2) How long shall we continue to do it?" (Barry Boehm, "A spiral model of software development and enhancement", IEEE, 1988)

"Every software system needs to have a simple yet powerful organizational philosophy (think of it as the software equivalent of a sound bite that describes the system's architecture). [A] step in [the] development process is to articulate this architectural framework, so that we might have a stable foundation upon which to evolve the system's function points." (Grady Booch, "Object-Oriented Design: with Applications", 1991)

"Testing by itself does not improve software quality. Test results are an indicator of quality, but in and of themselves, they don't improve it. Trying to improve software quality by increasing the amount of testing is like trying to lose weight by weighing yourself more often. What you eat before you step onto the scale determines how much you will weigh, and the software development techniques you use determine how many errors testing will find. If you want to lose weight, don't buy a new scale; change your diet. If you want to improve your software, don't test more; develop better." (Steve C McConnell, "Code Complete: A Practical Handbook of Software Construction", 1993)

"If a project has not achieved a system architecture, including its rationale, the project should not proceed to full-scale system development. Specifying the architecture as a deliverable enables its use throughout the development and maintenance process." (Barry Boehm, 1995)

"Successful software development is a team effort - not just the development team, but the larger team consisting of customer, management and developers. [...] Every software project needs to deliver business value. To be successful, the team needs to build the right things, in the right order, and to be sure that what they build actually works." (Ron Jeffries, "Extreme Programming Installed", 2001)

"Agile development methodologies promise higher customer satisfaction, lower defect rates, faster development times and a solution to rapidly changing requirements. Plan-driven approaches promise predictability, stability, and high assurance. However, both approaches have shortcomings that, if left unaddressed, can lead to project failure. The challenge is to balance the two approaches to take advantage of their strengths and compensate for their weaknesses." (Barry Boehm & Richard Turner, "Observations on balancing discipline and agility", Agile Development Conference, 2003)

"Computer programming is tremendous fun. Like music, it is a skill that derives from an unknown blend of innate talent and constant practice. Like drawing, it can be shaped to a variety of ends – commercial, artistic, and pure entertainment. Programmers have a well-deserved reputation for working long hours, but are rarely credited with being driven by creative fevers. Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination, but because their imagination reveals worlds that others cannot see." (Larry O'Brien & Bruce Eckel, "Thinking in C#", 2003)

"Design patterns give names to practical knowledge; they define a high-level vocabulary for understanding and solving business statements graphically. Design patterns are presented in a standard format; they're like recipes in a cookbook or dress patterns in a catalog. Above all, they are practical, first as instructional materials and then as development tools." (Alan Chmura & J Mark Heumann, "Logical Data Modeling: What it is and How to do it", 2005)

"Developing fewer features allows you to conserve development resources and spend more time refining those features that users really need. Fewer features mean fewer things to confuse users, less risk of user errors, less description and documentation, and therefore simpler Help content. Removing any one feature automatically increases the usability of the remaining ones." (Jakob Nielsen, "Prioritizing Web Usability", 2006)

"Communicating abstractions unambiguously - from programmer to machine, from programmer to programmer, and from program to user - is the single most challenging demand of software development." (Scott Rosenberg, "Dreaming in Code", 2007)

"[…] in software development, as in all things, plans get dodgier the farther into the future one looks. Any developer who has been around the block will admit that the cavalcade of methodologies over three decades of software history has left the field richer and given programmers useful new tools and ways of thinking about their work. But finding a developer or team that actually subscribes to a particular methodology isn’t easy." (Scott Rosenberg, "Dreaming in Code", 2007)

"The amateur software engineer is always in search of magic, some sensational method or tool whose application promises to render software development trivial. It is the mark of the professional software engineer to know that no such panacea exist." (Grady Booch et al, "Object-Oriented Analysis and Design with Applications", 2007) 

"The picture of digital progress that so many ardent boosters paint ignores the painful record of actual programmers’ epic struggles to bend brittle code into functional shape. That record is of one disaster after another, marking the field’s historical time line like craters. Anyone contemplating the start of a big software development project today has to contend with this unfathomably discouraging burden of experience. It mocks any newcomer with ambitious plans, as if to say, What makes you think you’re any different?" (Scott Rosenberg, "Dreaming in Code", 2007)

"Features have a specification cost, a design cost, and a development cost. There is a testing cost and a reliability cost. […] Features have a documentation cost. Every feature adds pages to the manual increasing training costs." (Douglas Crockford, "JavaScript: The Good Parts: The Good Parts", 2008)

"It is a myth that we can get systems 'right the first time'. Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow. This is the essence of iterative and incremental agility. Test-driven development, refactoring, and the clean code they produce make this work at the code level." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"The use of rapid prototyping methodologies is to reduce the production time by using working models of the final product early in a project tends to eliminate time-consuming revisions later on, and by completing design tasks concurrently, rather than sequentially throughout the project. The steps are crunched together to reduce the amount of time needed to develop training or a product. The design and development phases are done simultaneously and the formative evaluation is done throughout the process." (Irene Chen, "Instructional Design Methodologies", 2008)

"Programming is something some people do - some of the time. And the hard part - the thinking - is the least visible and least appreciated by the uninitiated. […] The persistent vision that software development can be simplified by removing programming is, to the programmer who understands what is involved, obviously naïve. But the mental process that leads to this mistake is part of human nature, and programmers are just as prone to making it as everyone else." (Alan Griffiths, [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"Agile approaches to software development consider design and implementation to be the central activities in the software process. They incorporate other activities, such as requirements elicitation and testing, into design and implementation. By contrast, a plan-driven approach to software engineering identifies separate stages in the software process with outputs associated with each stage." (Ian Sommerville, "Software Engineering" 9th Ed., 2011)

"Agile methods universally rely on an incremental approach to software specification, development, and delivery. They are best suited to application development where the system requirements usually change rapidly during the development process. They are intended to deliver working software quickly to customers, who can then propose new and changed requirements to be included in later iterations of the system. They aim to cut down on process bureaucracy by avoiding work that has dubious long-term value and eliminating documentation that will probably never be used." (Ian Sommerville, "Software Engineering" 9th Ed., 2011)

"Software development is a marathon, not a sprint. You can’t win the race by trying to run as fast as you can from the outset. You win by conserving your resources and pacing yourself. A marathon runner takes care of her body both before and during the race. Professional programmers conserve their energy and creativity with the same care." (Robert C Martin,"The Clean Coder: A code of conduct for professional programmers", 2011) 

"System engineering is concerned with all aspects of the development and evolution of complex systems where software plays a major role. System engineering is therefore concerned with hardware development, policy and process design and system deployment, as well as software engineering. System engineers are involved in specifying the system, defining its overall architecture, and then integrating the different parts to create the finished system. They are less concerned with the engineering of the system components (hardware, software, etc.)." (Ian Sommerville, "Software Engineering" 9th Ed., 2011)

"A value stream is a series of activities required to deliver an outcome. The software development value stream may be described as: validate business case, analyze, design, build, test, deploy, learn from usage analytics and other feedback - rinse and repeat." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"Development is a design process. Design processes are generally evaluated by the value they deliver rather than a conformance to plan. Therefore, it makes sense to move away from plan-driven projects and toward value-driven projects. […] The realization that the source code is part of the design, not the product, fundamentally rewires our understanding of software." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"DevOps recognizes the importance of culture. The acronym CAMS (culture, automation, measurement, and sharing) is used to encapsulate its key themes. Culture is acknowledged as all important in making development and IT operations work together effectively. But what is culture in this context? It is not so much about an informal dress code, flexible hours, or a free in-house cafeteria as it is about how decisions are taken, norms of behavior, protocols of communication, and the ways of navigating hierarchy and bureaucracy to get things done." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"Feedback is what makes it iterative; otherwise, it is just mini-waterfall. Merely splitting use cases into stories does not make for iterative development if we wait until all stories are developed before we seek feedback. The point of splitting is to get feedback faster so that it can be incorporated into ongoing development. However, seeking stakeholder/user feedback for small batches of functionality (stories) is often not feasible with formal stage-gate processes. They were conceived with linear flows of large batches in mind." (Sriram Narayan, "Agile IT Organization Design: For Digital Transformation and Continuous Delivery", 2015)

"A key contribution of DevOps was to raise awareness of the problems lingering in how teams interacted (or not) across the delivery chain, causing delays, rework, failures, and a lack of understanding and empathy toward other teams. It also became clear that such issues were not only happening between application development and operations teams but in interactions with many other teams involved in software delivery, like QA, InfoSec, networking, and more." (Matthew Skelton & Manuel Pais, "Team Topologies: Organizing Business and Technology Teams for Fast Flow", 2019)

03 December 2007

🏗️Software Engineering: Design Patterns (Just the Quotes)

"A pattern is a fully realized form original, or model accepted or proposed for imitation. With patterns, small piecework is standardized into a larger chunk or unit. Patterns become the building blocks for design and construction. Finding and applying patterns indicates progress in a field of human endeavor." (Peter Coad, "Object-oriented patterns", 1992) 

"A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in object-oriented systems. It describes the problem, the solution, when to apply the solution, and its consequences. It also gives implementation hints and examples. The solution is a general arrangement of objects and classes that solve the problem. The solution is customized and implemented to solve the problem in a particular context." (Erich Gamma et al, "Design Patterns: Elements of Reusable Object-Oriented Software", 1994)

"The purpose of a conceptual model is to provide a vocabulary of terms and concepts that can be used to describe problems and/or solutions of design. It is not the purpose of a model to address specific problems, and even less to propose solutions for them. Drawing an analogy with linguistics, a conceptual model is analogous to a language, while design patterns are analogous to rhetorical figures, which are predefined templates of language usages, suited particularly to specific problems." (Peter P Chen [Ed.], "Advances in Conceptual Modeling", 1999)

"In addition to their complexity-management benefit, design patterns can accelerate design discussions by allowing designers to think and discuss at a larger level of granularity." (Steve McConnell, "Code Complete" 2nd Ed., 2004)

"On small, informal projects, a lot of design is done while the programmer sits at the keyboard. 'Design' might be just writing a class interface in pseudocode before writing the details. It might be drawing diagrams of a few class relationships before coding them. It might be asking another programmer which design pattern seems like a better choice. Regardless of how it’s done, small projects benefit from careful design just as larger projects do, and recognizing design as an explicit activity maximizes the benefit you will receive from it." (Steve McConnell, "Code Complete" 2nd Ed., 2004)

"Software design patterns are what allow us to describe design fragments, and reuse design ideas, helping developers leverage the expertise of others. Patterns give a name and form to abstract heuristics, rules and best practices of object-oriented techniques." (Philippe Kruchten, [foreword] 2004)

"Design patterns give names to practical knowledge; they define a high-level vocabulary for understanding and solving business statements graphically. Design patterns are presented in a standard format; they're like recipes in a cookbook or dress patterns in a catalog. Above all, they are practical, first as instructional materials and then as development tools." (Alan Chmura & J Mark Heumann, "Logical Data Modeling: What it is and How to do it", 2005)

"Structural patterns describe how classes and objects can be combined to form larger structures. Patterns for classes describe how inheritance can be used to provide more useful program interfaces. Patterns for objects describe how objects can be composed into larger structures using object composition." (Junji Nakano et al, "Programming Statistical Data Visualization in the Java Language" [in "Handbook of Data Visualization"], 2008)

"Design patterns are high-level abstractions that document successful design solutions. They are fundamental to design reuse in object-oriented development." (Ian Sommerville, "Software Engineering" 9th Ed., 2011)

"Most designers think of design patterns as a way of supporting object-oriented design. Patterns often rely on object characteristics such as inheritance and polymorphism to provide generality. However, the general principle of encapsulating experience in a pattern is one that is equally applicable to all software design approaches." (Ian Sommerville, "Software Engineering" 9th Ed., 2011)

"A software design pattern is a reusable solution to a reoccurring software design problem. […] A design pattern is not a concrete design or implementation, such as an algorithm that can be used as-is, but rather a gene." (Eddie Burris, "Programming in the Large with Design Patterns", 2012)

"Knowledge of design patterns simplifies software design by reducing the number of design problems that have to be solved from first principles. Design problems that match documented design patterns have ready-made solutions. The remaining. problems that don't match documented design patterns must be solved from first principles. Even here, knowledge of design patterns can potentially help with original design. Design patterns are paragons of good design. Studying design patterns helps to develop the intellectual concepts and principles needed to solve unique design problems from first principles." (Eddie Burris, "Programming in the Large with Design Patterns", 2012)

"What makes a design pattern unique is its intent. The intent of a pattern is the problem solved or reason for using it. […] What distinguishes one pattern from another is the problem solved. You can infer the solution structure and problem solved from the pattern name but you can’t infer the pattern name from the solution structure alone." (Eddie Burris, "Programming in the Large with Design Patterns", 2012) 

"A design pattern usually suggests a scheme for structuring the classes in a design solution and defines the required interactions among those classes. In other words, a design pattern describes some commonly recurring structure of communicating classes that can be used to solve some general design problems. Design pattern solutions are typically described in terms of classes, their instances, their roles and collaborations." (Rajib Mall, "Fundamentals of Software Engineering" 4th Ed., 2014)

"If a pattern represents a best practice, then an antipattern represents lessons learned from a bad design. [...] Antipatterns are valuable because they help us to recognise why a particular design alternative might seem at first like an attractive solution, but later on lead to complicacies and finally turn out to be a poor solution." (Rajib Mall, "Fundamentals of Software Engineering" 4th Ed., 2014)

"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.''  (Christopher Alexander)

🏗️Software Engineering: Opportunities (Just the Quotes)

"Computers don’t introduce order anywhere as much as they expose opportunities." (Alan J Perlis, "Epigrams on Programming", 1982)

"Programming is like pinball. The reward for doing it well is the opportunity to do it again." (Rick Cook, "The Wizardry Compiled", 1989)

"A typical software project can present more opportunities to learn from mistakes than some people get in a lifetime." (Steve McConnell, "Rapid Development", 1996)

"Many things can put a project off course: bureaucracy, unclear objectives, and lack of resources, to name a few. But it is the approach to design that largely determines how complex software can become. When complexity gets out of hand, developers can no longer understand the software well enough to change or extend it easily and safely. On the other hand, a good design can create opportunities to exploit those complex features." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"As a noun, design is the named (although sometimes unnamable) structure or behavior of a system whose presence resolves or contributes to the resolution of a force or forces on that system. A design thus represents one point in a potential decision space. A design may be singular (representing a leaf decision) or it may be collective (representing a set of other decisions). As a verb, design is the activity of making such decisions. Given a large set of forces, a relatively malleable set of materials, and a large landscape upon which to play, the resulting decision space may be large and complex. As such, there is a science associated with design (empirical analysis can point us to optimal regions or exact points in this design space) as well as an art (within the degrees of freedom that range beyond an empirical decision; there are opportunities for elegance, beauty, simplicity, novelty, and cleverness). All architecture is design but not all design is architecture. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change." (Grady Booch, "On design", 2006)

"The majority of the cost of a software project is in long-term maintenance. In order to minimize the potential for defects as we introduce change, it’s critical for us to be able to understand what a system does. As systems become more complex, they take more and more time for a developer to understand, and there is an ever greater opportunity for a misunderstanding. Therefore, code should clearly express the intent of its author. The clearer the author can make the code, the less time others will have to spend understanding it. This will reduce defects and shrink the cost of maintenance." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"Just as it can accelerate the pace of a project, prototyping allows the exploration of many ideas in parallel. Early prototypes should be fast, rough, and cheap. The greater the investment in an idea, the more committed one becomes to it. Overinvestment in a refined prototype has two undesirable consequences: First, a mediocre idea may go too far toward realization - or even, in the worst case, all the way. Second, the prototyping process itself creates the opportunity to discover new and better ideas at minimal cost." (Tim Brown, "Change by Design: How Design Thinking Transforms Organizations and Inspires Innovation", 2009)

"Refactoring is the process of improving the design of existing code without changing its behavior. [...] Bug fixing often uncovers opportunities for refactoring. The very fact that you’re working with code that contains a bug indicates that there is a chance that it could be clearer or better structured." (Paul Butcher, "Debug It! Find, Repair, and Prevent Bugs in Your Code", 2009)

"Implementing new systems provides organizations with unique opportunities not only to improve their technologies, but to redefine and improve key business processes. Ultimately, for organizations to consider these new systems successes, the post-legacy environment must ensure that business processes, client end users, and systems work together." (Phil Simon, "Why New Systems Fail: An Insider's Guide to Successful IT Projects", 2010)

02 December 2007

🏗️Software Engineering: Quality Assurance (Just the Quotes)

"Program testing can be used to show the presence of bugs, but never to show their absence!" (Edsger W Dijkstra, "Notes On Structured Programming", 1970)

"It is a fundamental principle of testing that you must know in advance the answer each test case is supposed to produce. If you don't, you are not testing; you are experimenting." (Brian Kernighan, "Software Tools in Pascal", 1981)

"The essence of a software entity is a construct of interlocking concepts: […] I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation." (Fred Brooks, "No Silver Bullet", 1986)

"A design remedy that prevents bugs is always preferable to a test method that discovers them." (Boris Beizer, "Software Testing Techniques", 1990)

"A test that reveals a bug has succeeded, not failed." (Boris Beizer, "Software Testing Techniques", 1990)

"More than the act of testing, the act of designing tests is one of the best bug preventers known. The thinking that must be done to create a useful test can discover and eliminate bugs before they are coded - indeed, test-design thinking can discover and eliminate bugs at every stage in the creation of software, from conception to specification, to design, coding and the rest."  (Boris Beizer, "Software Testing Techniques", 1990)

"Programmers are responsible for software quality - quality in their own work, quality in the products that incorporate their work, and quality at the interfaces between components. Quality has never been and will never be tested in. The responsibility is both moral and professional." (Boris Beizer, "Software Testing Techniques", 1990)

"Testing proves a programmer’s failure. Debugging is the programmer’s vindication." (Boris Beizer, "Software Testing Techniques", 1990)

"First law: The pesticide paradox. Every method you use to prevent or find bugs leaves a residue of subtler bugs against which those methods are ineffective."  (Boris Beizer, "Software Testing Techniques", 1990)

"Second law: The complexity barrier. Software complexity (and therefore that of bugs) grows to the limits of our ability to manage that complexity." (Boris Beizer, "Software Testing Techniques", 1990)

"Software never was perfect and won't get perfect. But is that a license to create garbage? The missing ingredient is our reluctance to quantify quality." (Boris Beizer, "Software Testing Techniques", 1990)

"Third law: Code migrates to data. Because of this law there is increasing awareness that bugs in code are only half the battle and that data problems should be given equal attention."  (Boris Beizer, "Software Testing Techniques", 1990)

"The most common kind of coding bug, and often considered the least harmful, are documentation bugs (i.e., erroneous comments). Although many documentation bugs are simple spelling errors or the result of poor writing, many are actual errors - that is, misleading or erroneous comments. We can no longer afford to discount such bugs, because their consequences are as great as 'true' coding errors. Today programming labor is dominated by maintenance. This will increase as software becomes even longer-lived. Documentation bugs lead to incorrect maintenance actions and therefore cause the insertion of other bugs." (Boris Beizer, "Software Testing Techniques", 1990)

"Testing by itself does not improve software quality. Test results are an indicator of quality, but in and of themselves, they don't improve it. Trying to improve software quality by increasing the amount of testing is like trying to lose weight by weighing yourself more often. What you eat before you step onto the scale determines how much you will weigh, and the software development techniques you use determine how many errors testing will find. If you want to lose weight, don't buy a new scale; change your diet. If you want to improve your software, don't test more; develop better." (Steve C McConnell, "Code Complete: A Practical Handbook of Software Construction", 1993)

"The source code is often the only accurate description of the software. On many projects, the only documentation available to programmers is the code itself. Requirements specifications and design documents can go out of date, but the source code is always up to date. Consequently, it's imperative that the code be of the highest possible quality." (Steve C McConnell," Code Complete: A Practical Handbook of Software Construction", 1993) 

"The real value of tests is not that they detect bugs in the code, but that they detect inadequacies in the methods, concentration, and skills of those who design and produce the code." (Charles A R Hoare, "How Did Software Get So Reliable Without Proof?", Lecture Notes in Computer Science Vol. 1051, 1996)

"A system that is comprehensively tested and passes all of its tests all of the time is a testable system. That’s an obvious statement, but an important one. Systems that aren’t testable aren’t verifiable. Arguably, a system that cannot be verified should never be deployed." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"It is a myth that we can get systems 'right the first time'. Instead, we should implement only today’s stories, then refactor and expand the system to implement new stories tomorrow. This is the essence of iterative and incremental agility. Test-driven development, refactoring, and the clean code they produce make this work at the code level." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"It is unit tests that keep our code flexible, maintainable, and reusable. The reason is simple. If you have tests, you do not fear making changes to the code! Without tests every change is a possible bug."  (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

🏗️Software Engineering: Models (Just the Quotes)

"Models are models of something, namely, [they are] reflections, representations of natural and artificial originals, that can themselves be models again. […] Models, in general, do not cover all the attributes of the originals they are representing, but only those [attributes] that seem relevant to the actual model creators and/or model users." (Herbert Stachowiak, "Allgemeine Modelltheorie", 1973)

"Models are not assigned per se uniquely to their originals. They perform their replacement function: a) for definite – cognitive and/or handling, model-using – subjects, b) within definite time intervals, c) under restrictions of definite operations of thought or fact. […] Models are not only models of something. They are also models for somebody, a human or an artificial model user. They perform thereby their functions in time, within a time interval. And finally, they are models for a definite purpose." (Herbert Stachowiak, "Allgemeine Modelltheorie", 1973)

"A model is an attempt to represent some segment of reality and explain, in a simplified manner, the way the segment operates." (E Frank Harrison, "The managerial decision-making process" , 1975)

"The aim of the model is of course not to reproduce reality in all its complexity. It is rather to capture in a vivid, often formal, way what is essential to understanding some aspect of its structure or behavior." (Joseph Weizenbaum, "Computer power and human reason: From judgment to calculation" , 1976)

"A pattern is a fully realized form original, or model accepted or proposed for imitation. With patterns, small piecework is standardized into a larger chunk or unit. Patterns become the building blocks for design and construction. Finding and applying patterns indicates progress in a field of human endeavor." (Peter Coad, "Object-oriented patterns", 1992)

"Model building is the art of selecting those aspects of a process that are relevant to the question being asked. As with any art, this selection is guided by taste, elegance, and metaphor; it is a matter of induction, rather than deduction. High science depends on this art." (John H Holland," Hidden Order: How Adaptation Builds Complexity", 1995)

"Another curious phenomenon you may meet is in fitting data to a model there are errors in both the data and the model. For example, a normal distribution may be assumed, but the tails may in fact be larger or smaller than the model predicts, and possibly no negative values can occur although the normal distribution allows them. Thus there are two sources of error. As your ability to make more accurate measurements increases the error due to the model becomes an increasing part of the error." (Richard Hamming, "The Art of Doing Science and Engineering: Learning to Learn", 1997)

"We tend to form mental models that are simpler than reality; so if we create represented models that are simpler than the actual implementation model, we help the user achieve a better understanding. […] Understanding how software actually works always helps someone to use it, but this understanding usually comes at a significant cost. One of the most significant ways in which computers can assist human beings is by putting a simple face on complex processes and situations. As a result, user interfaces that are consistent with users’ mental models are vastly superior to those that are merely reflections of the implementation model." (Alan Cooper et al,  "About Face 3: The Essentials of Interaction Design", 2007)

"The methods of science include controlled experiments, classification, pattern recognition, analysis, and deduction. In the humanities we apply analogy, metaphor, criticism, and (e)valuation. In design we devise alternatives, form patterns, synthesize, use conjecture, and model solutions." (Béla H Bánáthy, "Designing Social Systems in a Changing World", 1996)

"If the design, or some central part of it, does not map to the domain model, that model is of little value, and the correctness of the software is suspect. At the same time, complex mappings between models and design functions are difficult to understand and, in practice, impossible to maintain as the design changes. A deadly divide opens between analysis and design so that insight gained in each of those activities does not feed into the other." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"Models come in many varieties and serve many roles, even those restricted to the context of a software development project. Domain-driven design calls for a model that doesn’t just aid early analysis but is the very foundation of the design […]  Tightly relating the code to an underlying model gives the code meaning and makes the model relevant." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"The effectiveness of an overall design is very sensitive to the quality and consistency of fine-grained design and implementation decisions. With a MODEL-DRIVEN DESIGN, a portion of the code is an expression of the model; changing that code changes the model. Programmers are modelers, whether anyone likes it or not. So it is better to set up the project so that the programmers do good modeling work." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"The technical model that drives the software development process must be strictly pared down to the necessary minimum to fulfill its functions. An explanatory model can include aspects of the domain that provide context that clarifies the more narrowly scoped model. Explanatory models offer the freedom to create much more communicative styles tailored to a particular topic. Visual metaphors used by the domain experts in a field often present clearer explanations, educating developers and harmonizing experts. Explanatory models also present the domain in a way that is simply different, and multiple, diverse explanations help people learn." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"To create software that is valuably involved in users' activities, a development team must bring to bear a body of knowledge related to those activities. The breadth of knowledge required can be daunting. The volume and complexity of information can be overwhelming. Models are tools for grappling with this overload. A model is a selectively simplified and consciously structured form of knowledge. An appropriate model makes sense of information and focuses it on a problem." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"When a design is based on a model that reflects the basic concerns of the users and domain experts, the bones of the design can BE revealed to the user to a greater extent than with other design approaches. Revealing the model gives the user more access to the potential of the software and yields consistent, predictable behavior." (Eric Evans, "Domain-Driven Design: Tackling complexity in the heart of software", 2003)

"The use of rapid prototyping methodologies is to reduce the production time by using working models of the final product early in a project tends to eliminate time-consuming revisions later on, and by completing design tasks concurrently, rather than sequentially throughout the project. The steps are crunched together to reduce the amount of time needed to develop training or a product. The design and development phases are done simultaneously and the formative evaluation is done throughout the process." (Irene Chen, "Instructional Design Methodologies", 2008)

"A good system design is based on a sound conceptual model (architecture). A system design that has no conceptual structure and little logic to its organization is ultimately going to be unsuccessful. Good architecture will address all the requirements of the system at the right level of abstraction." (Vasudeva Varma, "Software Architecture: A Case Based Approach", 2009)

"Although it might seem as though frittering away valuable time on sketches and models and simulations will slow work down, prototyping generates results faster." (Tim Brown, "Change by Design: How Design Thinking Transforms Organizations and Inspires Innovation", 2009)

"Less apparent is that qualitatively different problem-solving techniques are required at high levels of complexity than at low ones. Purely analytical techniques, powerful for the lower levels, can be overwhelmed at the higher ones. At higher levels, architecting methods, experience-based heuristics, abstraction, and integrated modeling must be called into play." (Mark W Maier, "The Art Systems of Architecting" 3rd Ed., 2009)

"Modeling is the creation of abstractions or representations of the system to predict and analyze performance, costs, schedules, and risks and to provide guidelines for systems research, development, design, manufacture, and management. Modeling is the centerpiece of systems architecting - a mechanism of communication to clients and builders, of design management with engineers and designers, of maintaining system integrity with project management, and of learning for the architect, personally." (Mark W Maier, "The Art Systems of Architecting" 3rd Ed., 2009)

"Modeling is the fabric of architecting because architecting is at a considerable distance of abstraction from actual construction. The architect does not manipulate the actual elements of construction. The architect builds models that are passed into more detailed design processes. Those processes lead, eventually, to construction drawings or the equivalent and actual system fabrication or coding." (Mark W Maier, "The Art Systems of Architecting" 3rd Ed., 2009)

"The basic idea behind all of these techniques is to simplify problem solving by concentrating on its essentials. Consolidate and simplify the objectives. Focus on the things with the highest impact, things that determine other things. Put to one side minor issues likely to be resolved by the resolution of major ones. Discard the nonessentials. Model (abstract) the system at as high a level as possible, then progressively reduce the level of abstraction. In short: Simplify!" (Mark W Maier, "The Art Systems of Architecting" 3rd Ed., 2009)

"Making domain concepts explicit in your code means other programmers can gather the intent of the code much more easily than by trying to retrofit an algorithm into what they understand about a domain. It also means that when the domain model evolves - which it will, as your understanding of the domain grows - you are in a good position to evolve the code. Coupled with good encapsulation, the chances are good that the rule will exist in only one place, and that you can change it without any of the dependent code being any the wiser." (Dan North [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010]) 

"A complete data analysis will involve the following steps: (i) Finding a good model to fit the signal based on the data. (ii) Finding a good model to fit the noise, based on the residuals from the model. (iii) Adjusting variances, test statistics, confidence intervals, and predictions, based on the model for the noise.(DeWayne R Derryberry, "Basic data analysis for time series with R", 2014)

 "A wide variety of statistical procedures (regression, t-tests, ANOVA) require three assumptions: (i) Normal observations or errors. (ii) Independent observations (or independent errors, which is equivalent, in normal linear models to independent observations). (iii) Equal variance - when that is appropriate (for the one-sample t-test, for example, there is nothing being compared, so equal variances do not apply).(DeWayne R Derryberry, "Basic data analysis for time series with R", 2014)

"Once a model has been fitted to the data, the deviations from the model are the residuals. If the model is appropriate, then the residuals mimic the true errors. Examination of the residuals often provides clues about departures from the modeling assumptions. Lack of fit - if there is curvature in the residuals, plotted versus the fitted values, this suggests there may be whole regions where the model overestimates the data and other whole regions where the model underestimates the data. This would suggest that the current model is too simple relative to some better model.(DeWayne R Derryberry, "Basic data analysis for time series with R", 2014)

"Prediction about the future assumes that the statistical model will continue to fit future data. There are several reasons this is often implausible, but it also seems clear that the model will often degenerate slowly in quality, so that the model will fit data only a few periods in the future almost as well as the data used to fit the model. To some degree, the reliability of extrapolation into the future involves subject-matter expertise.(DeWayne R Derryberry, "Basic data analysis for time series with R", 2014)

 "The random element in most data analysis is assumed to be white noise - normal errors independent of each other. In a time series, the errors are often linked so that independence cannot be assumed (the last examples). Modeling the nature of this dependence is the key to time series.(DeWayne R Derryberry, "Basic data analysis for time series with R", 2014)

"Design is the process of taking something that appears in the mind’s eye, modeling it in one or more of a number of ways, predicting how that thing will behave if it is made, and then making it, sometimes modifying the design as we make it. Design is what engineering is about. Furthermore, modeling is how engineering design is done. This includes mental models, mathematical models, computer models, plans and drawings, written language, and (sometimes) physical models." (William M Bulleit, "The Engineering Way of Thinking: The Idea", Structure [magazine], 2015) 

🏗️Software Engineering: Annotations (Just the Quotes)

"Don’t comment bad code - rewrite it." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"Don't just echo the code with comments make every comment count." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"Make sure comments and code agree." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"Notice that even the data is commented. One of the most effective ways to document a program is simply to describe the data layout in detail. If you can specify for each important variable what values it can assume and how it gets changed, you have gone a long way to describing the program. [...] Document your data layouts." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"The best documentation for a computer program is a clean structure. It also helps if the code is well formatted, with good mnemonic identifiers and labels (if any are needed), and a smattering of enlightening comments. Flowcharts and program descriptions are of secondary importance; the only reliable documentation of a computer program is the code itself. The reason is simple -whenever there are multiple representations of a program, the chance for discrepancy exists. If the code is in error, artistic flowcharts and detailed comments are to no avail. Only by reading the code can the programmer know for sure what the program does." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"Writing a computer program eventually boils down to writing a sequence of statements in the language at hand. How each of those statements is expressed determines in large measure the intelligibility of the whole; no amount of commenting, formatting, or supplementary documentation can entirely replace well expressed statements. After all, they determine what the program actually does." (Brian W Kernighan & Phillip J Plauger, "The Elements of Programming Style", 1974)

"The most common kind of coding bug, and often considered the least harmful, are documentation bugs (i.e., erroneous comments). Although many documentation bugs are simple spelling errors or the result of poor writing, many are actual errors - that is, misleading or erroneous comments. We can no longer afford to discount such bugs, because their consequences are as great as 'true' coding errors. Today programming labor is dominated by maintenance. This will increase as software becomes even longer-lived. Documentation bugs lead to incorrect maintenance actions and therefore cause the insertion of other bugs." (Boris Beizer, "Software Testing Techniques", 1990)

"Any comment that forces you to look in another module for the meaning of that comment has failed to communicate to you and is not worth the bits it consumes." (Robert C Martin, "Clean Code: A Handbook of Agile Software Craftsmanship", 2008)

"Obsolete comments are worse than no comments." (Douglas Crockford, "JavaScript: The Good Parts", 2008)

"Comments are not evil. They are as necessary to programming as basic branching or looping constructs. […] On the other hand, you can go too far in your commenting. Make sure that your comments clarify your code but do not obscure it. Sprinkle your code with relevant comments explaining what the code is supposed to accomplish. Your header comments should give any programmer enough information to use your code without having to read it, while your inline comments should assist the next developer in fixing or extending it." (Cal Evans [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"Comments that parrot the code offer nothing extra to the reader - stating something once in code and again in natural language does not make it any truer or more real. Commented-out code is not executable code, so it has no useful effect for either reader or runtime. It also becomes stale very quickly. […] A prevalence of noisy comments and incorrect comments in a codebase encourages programmers to ignore all comments, either by skipping past them or by taking active measures to hide them. Programmers are resourceful and will route around anything perceived to be damage: folding comments up; switching coloring scheme so that comments and the background are the same color; scripting to filter out comments." (Kevlin Henney, [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

"If your code needs comments, consider refactoring it so it doesn’t. Lengthy comments can clutter screen space and might even be hidden automatically by your IDE. If you need to explain a change, do so in the version control system check-in message and not in the code." (Peter Sommerlad, [in Kevlin Henney’s "97 Things Every Programmer Should Know", 2010])

Related Posts Plugin for WordPress, Blogger...

About Me

My photo
Koeln, NRW, Germany
IT Professional with more than 25 years experience in IT in the area of full life-cycle of Web/Desktop/Database Applications Development, Software Engineering, Consultancy, Data Management, Data Quality, Data Migrations, Reporting, ERP implementations & support, Team/Project/IT Management, etc.