CC Flashcards

(90 cards)

1
Q

What is the 5S philosophy?

A

A set of principles part of the Total Productive Maintenance (TPM) where the focus is on maintenance instead of producing.

  1. Seiri, or organization. Knowing where things are - suitable names.
  2. Seiton, or tidiness. A piece of code should be where we expect to find it.
  3. Seiso, or cleaning. Clean workspace remove litter in code.
  4. Seiketsu, or standardization. Consistent code style and practices.
  5. Shutsuke, or discipline. Have the discipline to follow the practices.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is LeBlanc’s law?

A

Later equals never

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is clean code?

A
  1. Clean code is focused
  2. Decisive and matter-of-fact without unncessary details.
  3. Tested
  4. No surprises
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What is the boy scout rule?

A

The code has to be kept clean over time. The rule is:

leave the campground cleaner than you found it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What are intention-revealing names?

A

A name that reveals intent. A name should tell us why the entity exists.

Problem with bad names is that they increase the implicity of the code; the degree to which the context is not explicit in the code itself.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is disinformation in code?

A

We must avoid leaving false clues that obscure the meaning of code.

Or names that vary in small ways.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What about meaningful distinctions in names?

A

If names must be different, then they should also mean something different.

Noise words are another meaningless distinction. If we have ProductInfo and ProductData, then we have made the names different, without changing the meaning, since Data and Info are noise words.

Distinguish names in such a way that the reader knows what the differences offer.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What about using searchable names?

A

The length of a name should correspond to the size of its scope. If a variable or constant might be seen or used in multiple places in a body of code, it is imperative to give it a search-friendly name.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What about encodings in interface names?

A

Common in legacy but we are generally not interested in letting users/developers know that an API is handing them an Interface, they do not need to know these details, hence we should not encode interfaces in any special way.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How to name classes?

A

Classes and objects should have noun or noun phrase names like Customer, WikiPage, AddressParser.

Avoid words like Manager, Processor, Data, or Info in the name of a class. As these indicate god classes.

A class name should not be a verb.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How to name methods?

A

Methods should have verb or verb phrase names like postPayment, deletePage or save.

When constructors are overloaded use static factory methods with names that describe the arguments.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the first rule of creating functions?

A

They have to be small. Functions should not be large enough to hold nested structures.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is the second rule of creating functions?

A

They should do one thing. A function an perform multiple steps but each step has to be on the same abstraction level given the function name. After all the reason we write functions is to decompose a larger concept (function name) into a set of steps.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How can we check if a function is doing more than one thing?

A

If we can extract another function from it with a name that is not merely a restatement of its implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Why is it important to have only one level of abstraction per function?

A

Mixing levels of abstraction within a function is always confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. Once details are mixed with essential concepts, more and more details tend to accrete within the function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How can we handle the do N thing nature of switch statements?

A

We bury them in a low-level class and never repeat them. The appropriate switch is then called through polymorphism.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Why are flag arguments a bad idea?

A

Immediately complicates the signature and proclaims that the method does more than one thing.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

How to handle methods that take many arguments?

A

When a function needs more than one argument, it is likely that come of those arguments ought to be wrapped in class. Since the arguments are part of a concept that deserves a name of its own.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

What is the problem with side effects in functions?

A

Side effects are lies. They often result in strange temporal couplings and order dependencies.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What is command query separation?

A

Functions should either do something or answer something, but not both.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

How to should we extract try/catch blocks?

A

Separate functions into error processing and the actual command. Functions should do one thing, and error handling is one thing.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Why are comments not good?

A

Noisy. Have to be maintained. Might be wrong. Might cause confusion if not written properly. Might be redundant.

Write Javadocs on public APIs when its not simply restating what the function name already says.

Use small functions with good names instead of comments.

Comments should not be necessary if we could expressive ourselves properly in code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Why is code formatting important?

A
  1. If code is poorly formatted then it sends a signal to any reader that the same inattentiveness to detail pervades every other aspect of the code.
  2. Readability/Maintainability since formatting help separating into logical units and keeping concepts that are closely vertically close.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Why should we not use horizontal alignment of declarations?

A

They emphasize the wrong things and leads eyes away from their types. The real problem is the length (number of) declarations.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
What is one of the reasons to keep our variables private?
We do not want anyone else to depend on them. Consider getter and setters in this context.
26
What is hiding implementations about?
Its about abstractions. A class does not simply push its variables out through getter and setters. Rather it exposes abstract interfaces that allow its users to manipulate the essence of the data, without having to know its implementation. We want to express data in abstract terms that relate to the concept a class tries to capture.
27
What is the difference between objects and data structures?
Objects hide their data behind abstractions and expose functions that operate on that data. Data structures expose their data and have no meaningful functions. Procedural code (using data structures) makes it easy to add new functions without changing the existing data structures. OO code makes it easy to add new classes without changing existing functions.
28
Why is "everything is an object" a myth?
Dichotomy between objects and data structures. Some times we really want simple data structures with procedures operating them. Thereby having the flexibility to add new behaviors to existing data structures. Other times we want to make it easy to add new objects.
29
What is the law of Demeter?
It is a well-known heuristic that says a module should know about the innards of the objects it manipulates. A method f of a class C should only call the methods of these: 1. C 2. An object created by f 3. An object passed as an argument to f 4. An object help in an instance of variable C The method should not invoke methods on objects that are returned by any of the allowed functions. Minimizes coupling between modules.
30
What are some ways to write clean and robust code that handles errors (does not obscure the logic)?
1. Use exceptions rather than return codes: - Easy to forget to check return codes and they clutter the algorithm - Exceptions are easy to separate from the algorithm hence the algorithm can be much cleaner. 2. Write Try-Catch-Finally first: - Try to write tests that force exceptions, and then add behaviour to the code to satisfy that tests. 3. Use unchecked exceptions: - The price of checked exceptions is an Open/Closed Principle violation. Changes in low level signatures can force changes in higher levels. - Can be useful if we are writing critical libraries. But in general applications the cost outweigh the price. 4. Provide context with exceptions: - Enough context to determine the source and location of the exception (stack trace not enough). 5. Wrapping third party exceptions into a custom defined exception, if the handling is roughly the same for each exception in our end. 6. The special case pattern: - We create a class so that it handles the special case for us instead of handling in the client code, which clutters. 7. Do not return null: - Instead of null consider throwing an exception or returning a Special Case object. - If null from a third party consider wrapping it such that it throws an exception or returns a Special Case object.
31
Why boundaries between third-party APIs or internal external APIs should be hidden?
The third party API can evolve without affecting the application except for the few boundary classes that the rest of the application uses. Its not every map that should be encapsulated but consider not parsing raw boundary objects such as Maps around throughout the entire application, as API boundary objects can change and would have to be fixed in many places.
32
What are learning tests?
Writing tests of third party libraries related to how we will use them. To both explore and learn the behaviours of the third party software. They verify that the third party packages work as we expect and when the packages change, we know which behaviours now work in a new way.
33
How do we manage third party boundaries?
Have few places in the code that refer to them. We may wrap them, or use an Adapter to convert from our interface to their interface. Either way we need as few maintenance points in our application as possible.
34
What are the three laws of TDD?
1. We may not write production code until we have written a failing unit test. 2. We may not write more of a unit test than is sufficient to fail, and not compiling is failing. 3. We may not write more production code than is sufficient to pass the currently failing test.
35
Why is it important to have clean tests?
Developing with TDD means we write a lot of tests everyday. The bulk of the tests can present a daunting management problem. The test have to be updated when the production code and requirements change, hence dirty tests can become an increasing liability as time goes on. Test code is just as important as production code. It requires thought, design and care. It must be kept as clean as production code.
36
Why are tests so important?
Without tests we lose the thing that keeps the production code flexible, maintainable and reusable. With tests we do not have to fear making changes.
37
What makes a test clean?
Readability (clarity, simplicity, and density of expression). Try to minimize the details written in tests, they often result in information overload making it hard to quickly reason about them.
38
What is the F.I.R.S.T in the context of clean tests?
It is an acronym of five rules. Fast: Tests should be fast. Long tests are not run frequently, meaning; never. Independent: Tests should not depend on each other. Repeatable: Tests should be repeatable in any environment (during deployment, workstation etc.) Self-Validating: Single boolean output: pass or fail. Tests should not require one to read through output text etc. Timely: The tests should be written in a timely fashion. Production code should be designed such that it is testable.
39
What is the first rule of classes?
They should be small. The size of a classes is measured in number of responsibilities. Classes should only have one reason to change. The more ambiguous the class name, the more likely it has too many responsibilities.
40
Why is SRP often the most abused principle?
Getting software to work and making software clean are two very different activities. Many think we are done when the program works. Also many are concerned that having a large number of single-purpose classes make the system harder to read, due to having many classes that have to be read. However; there are just as many things to learn no matter what, but with smaller classes, we simply have a larger number of well-labeled tools. Larger classes forces us to learn more things than we actually need, when maintaining the system.
41
What does it mean to have high cohesion in a class and why do we want that?
It means that each method of a classes use a large subset of the instance variables. This suggests that the classes is one logical unit. If we have low cohesion in a classes, it suggests that we could split the class.
42
Why should we design classes to reduce the risk of change?
Every change subjects us to the risk that the remainder of the system no longer works as intended and is not a way to earn big bucks. In an ideal system, we incorporate new features by extending the system, not by making modifications to existing code.
43
How do we isolate of classes from change?
Decoupling components by depending on abstractions when necessary (e.g. in cases with external dependencies or factors). This also makes the system more easy to tests, also minimizing the risks of changes.
44
Why are abstractions and separation of concerns important?
In the real world large systems are managed by a lot of people that focus on different things where few if any know the details of every subsystem. In development we rarely see the same degree of separation and abstraction as real life examples such as cities. However, clean code at the systems levels enables us to work on subsystems without understanding the entire system.
45
Why is it important to separate runtime logic from construction logic?
By mixing construction logic (creating dependencies) with runtime logic (business logic) we first of all make it hard to test. But the system is also tightly bound to the dependencies we create in the middle or close to the business logic. We should therefore resolve all external dependency setup before entering the realm of business/runtime logic.
46
How can we separate runtime logic from construction logic?
1. Build everything in main, use abstract factories when we need to construct things in the runtime logic outside mains knowledge area. 2. Dependency injection.
47
Why are systems not just implemented right the first time?
Often we cannot anticipate growth or requirements and justifying features can be hard with a concrete need. we should therefore seek to today's requirements and then refactor and solve future problems in the future.
48
What is Aspect-oriented programming in the context of separating concerns?
AOP is a general-purpose approach to restoring modularity for cross-cutting concerns. A cross-cutting concern is a concern (essentially the same) that is shared by many domain objects (for example persistence we want to store objects using the same method, names etc.).
49
What are the most important terms in aspect-oriented programming?
1. Crosscutting concerns, it is code which should be moved in separate module. 2. Aspect, it is a module which contains concerns. 3. Pointcut, we can look at it as pointer which will instruct when corresponding code should be run. 4. Advice, it contains code which should be run when some join point is reached. 5. Inner-type declaration, allow modification of class structure. 6. Aspect-weaving, is mechanism which coordinate the integration with the rest of the system.
50
What is so cool about AOP like approaches?
We can write our domain logic using POJOs, decoupled from any architecture concerns at the code level. We can evolve the architecture from simple to sophisticated, as needed adopting new technologies on demand. It is not necessary to do a Big Design Up Front.
51
Why can Big Design Up Front (BDUF) be harmful?
It inhibits adapting to change, due to the psychological resistance to discarding prior effort and because of the way architecture choices influence subsequent thinking about the design. In software it is economically feasible to make radical change, if the structure of the software separates its concerns effectively.
52
What does an optimal system architecture look like?
It consists of modularized domains of concern, each of which are implemented with Plain Old Java Objects. The different domains are integrated together with minimally invasive Aspect or Aspect-like tools. This architecture can be test-driven, just like the code.
53
When is it the best time to make a decision?
At the last possible moment. This lets us make informed decisions with the best information. A premature decision is a decision made with suboptimal knowledge.
54
What are Kent Beck's four rules of simple design?
1. Runs all the tests. Systems that are testable are not verifiable. A system that cannot be verified should never be deployed. Having testing as a requirement pushes us towards low coupling and high cohesion within classes. 2. Contains no duplication. The template method pattern is a common technique for removing higher-level duplication. 3. Expresses the intent of the programmer. 4. Minimizes the number of classes and methods.
55
What can we do once we have tests?
Once we have tests we can refactor. During the refactoring step we can apply all of our knowledge about good design: increase cohesion within classes, decrease coupling, separate concerns, modularize system concerns, shrink functions and classes etc. This is also where we eliminate duplication, ensure expressiveness, and minimize the number of classes and methods.
56
Why is important for code to be expressive?
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 is critical for us to be able to understand what a system does. 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.
57
How do we write expressive code?
1. Choose good names 2. Keeping functions and classes small 3. Design patterns are largely about communication and expressiveness. 4. Well-written unit tests are also expressive. A primary goal of tests is to act as documentation by example. 5. Try. Take pride in your workmanship.
58
Why should we keep the number of classes and methods to a minimum?
Elimination of duplication, expressiveness and SRP can be taken too fare. High class and method counts can sometimes be the result of pointless dogmatism. Our goal is to keep our system small while we are also keeping our functions and classes small. However, this has lower priority compared with expressiveness, duplication and SRP.
59
What are the two main possibilities in terms of where an operations spends its time?
1. I/O - using a socket, connecting to a database, waiting for virtual memory swapping etc. 2. Processor - numerical calculations, regular expression processing, garbage collection. Systems typically have some of each but one tends to dominate. If the process is I/O bound, then concurrency can increase efficiency. When one part of the system is waiting for I/O, another part can use that wait time to process something else, making more effective use of the available CPU.
60
Why should thread management be kept to a few places?
To keep concurrency code clean and not violate the SRP. Any code that manages threads should not contain anything else, since it is hard enough to debug thread management without anything else.
61
When is a Future in Java handy?
When code needs to execute multiple, independent operations and wait for both to finish. Future.get() blocks until the future completes.
62
What are nonblocking solutions to concurrency in Java?
Java VM takes advantage of modern processor design, which supports reliable nonblocking updates. AtomicBoolean, AtomicInteger and AtomicReference. They perform better then the synchronize keyword.
63
Why are nonblocking Java objects faster than the synchronize keyword?
Modern processors have an operation called Compare and Swap (CAS). This operation is like optimistic locking, whereas synchronize is like pessimistic locking. The synchronize keyword always acquires a lock, even when a second thread is not trying to update the same value. Performance of locks is still costly even though performance have improved.
64
How does nonblocking solutions solve concurrency issues?
The nonblocking version starts with the assumption that multiple threads generally do not modify the same value often enough that a problem will arise. Instead, it efficiently detects whether such a situation has occurred and retries until the update happens successfully. This detection is almost always less costly than acquiring a lock, even in moderate to high contention situations. This operations is accomplished with CAS which is atomic.
65
What are nonthread-safe classes?
There are some classes that are inherently not thread safe: - SimpleDateFormat - Database Connections - Containers in java.util - Servlets Note that some collection classes have individual methods that are thread-safe. However, any operation that involves calling more than one method is not.
66
How can we make collections thread-safe?
There are several options: - Use locks (synchronize the collection) - Wrap the collection and use synchronize on the method that should be thread-safe - Use thread-safe collections in java.util.concurrent
67
How can dependencies between methods break concurrency?
If we use synchronize on the methods but the underlying field is not synchronized then dependencies between the synchronized methods might cause concurrency issues due to the underlying field value not being synchronized. Solutions: - tolerate errors (sucks sloppy) - client-based locking (sucks, we might forget) - server-based locking (reduces repeated code, allows better performance, reduces possibility of error, enforces a single policy, reduces scope of shared variable client is not aware). If we do not own the code, then we can use an adapter to change the API.
68
Why is it better to synchronize as little as possible?
To increase throughput since this reduces the amount of locking necessary.
69
What four conditions are required for a deadlock to occur?
1. Mutual exclusion: resources cannot be used by multiple threads at once. 2. Lock & wait: resources are not released until the thread is done using them. 3. No preemption: resources cannot be taken from other threads until they release them 4. Circular wait: multiple threads wait for each others resources.
70
What is starvation and livelock?
Starvation: One thread keeps being unable to acquire the resources it needs. Livelock: Several threads might get into lockstep and all acquire one resource and then release one resource over and over again.
71
What is monte carlo testing?
Tests are flexible, so they can be tuned with parameters. Then test are run over and over again, randomly changing the tuning parameters. If the tests every fail, then the code is broken.
72
Why employ concurrency?
Concurrency is a doubling strategy. It helps us decouple what gets done from when it gets done. Decoupling what from when can dramatically improve both the throughput and the structure of an application.
73
Does concurrency always improve performance?
Concurrency can sometimes improve performance, but only when there is a lot of wait time that can be shared between multiple threads or multiple processors.
74
What makes concurrent programming so difficult?
Concurrency bugs are not usually repeatable, so they are often ignored as one-offs instead of true defects. Additionally, when the JIT compiler compiles programs the number of execution paths becomes very large in many cases and some of them can return the wrong result sometimes.
75
How can we defend our system from the problems of concurrent code?
1. Single responsibility principle - concurrency design is complex and should be separated from the rest of the code. Concurrency related has its own life cycle of development, change and tuning. Concurrency related code has its own challenges. 2. Limit the scope of data - it is important to restrict the number of critical sections within our code. The more places shared data can get updated, the more likely we forget to protect the critical sections, duplication of protection mechanisms, more difficult to determine the source of errors. 3. Use copies of data - in some situations it is possible to copy objects and treat them as read-only. Before using we should experiment that avoiding locking performs better with the additional overhead of object copy and garbage collection. 4. Threads should be as independent as possible - consider writing threaded code such that each thread exists in its own world.
76
What things should be consider before writing concurrent code in Java 5 and above?
1. Use the provided thread-safe collections? 2. Use the executor framework for executing unrelated tasks. 3. Use nonblocking solutions when possible. 4. Several library classes are not thread-safe.
77
What are bound resources?
Resources of a fixed size or number used in a concurrent environment. For example database connections and fixed-size read/write buffers.
78
What leads to livelocks?
For example the total number of allowed processes in some systems, is determined by the number of entries in the process table. Thus process table slots can be referred to as bound resources. If a fork fails because of the table being full, waiting a random time and trying again would be a reasonable approach for the program doing the fork. Then if several processes proceed to create several subprocesses and exhaust the process table, each process can sit in an endless loop forking and failing loop.
79
What is the difference between deadlock and livelock?
The resulting effect is similar in that no actual work is done. In a livelock the states of the processes involved constantly change with regard to one another.
80
What are the most basic concurrent execution models?
Most concurrent problems we encounter is a variation of these problems. 1. Producer-Consumer - one or more producer threads create some work and place it in a buffer or queue. One or more consumers acquire resources from the queue. The queue or buffer is a bound resource. 2. Readers-Writers - have a shared resource that primarily serves as a source of information for readers, but is occasionally updated by writers. Writers tend to block many readers for a long time, thus causing throughput issues. The challenge it to balance the needs of both readers and writers to satisfy correct operation, providing reasonable throughput and avoid starvation. 3. Dining Philosophers - threads need resources to complete their work and compete for these resources with other threads and processes. Unless carefully designed, systems that compete for resources can experience deadlock, livelock, throughput issues and efficiency degradation.
81
Why should we beware of dependencies between synchronized methods?
Dependencies between synchronized methods cause subtle bugs in concurrent code. If there is more than one synchronized method on the same shared class, they the system may have been written incorrectly.
82
What are inappropriate information in comments?
Information better held in a different kind of system such as the source code control system, issue tracking system, or any other record-keeping system. Change histories, for example, clutter up source files. Comments should be reserved for technical notes about the code and design.
83
Why are obsolete comments a code smell?
They become floating islands of irrelevance and misdirection in the code.
84
Why are redundant comments a code smell?
Clutter. Comments should say things that the code cannot say for itself.
85
What is the principal of least surprise?
Any function or class should implement the behaviors that another programmer could reasonably expect.
86
Why is coding at the wrong abstraction level a code smell?
It is important to create abstractions that separate higher level general concepts from lower level detailed concepts. We want all the lower level concepts to be in the derivatives and all the higher level concepts to be in the base class. This rule also pertains to source files, components, and modules. Good software design requires that we separate concepts at different levels and place them in different containers. We cannot lie or fake our way out of a misplaced abstraction. Isolating abstractions is one of the hardest things that software developers do, and there is not quick fix when we get it wrong.
87
Why is feature envy a code smell?
The methods of a class should be interested in the variables and functions of the class they belong to, and not the variables and functions of other classes. When a method uses accessors and mutators of some other object to manipulate the data within the object, then it envies the scope of the class. It wishes it were inside that other class. Sometimes feature envy is a necessary evil to uphold SRP.
88
Why are selector arguments a code smell?
The purpose of a selector argument is hard to remember so we have to read the implementation details to understand its purpose. Selector arguments are also a lazy solution to splitting a large method.
89
Why should names describe side-effects?
Easier to read and names should not hide side-effects. For example, getOos vs createOrReturnOos.
90
Why is it important to choose names at the appropriate level of abstraction?
We should not pick names that communication implementation; we should choose names that reflect the level of abstraction of the class or function we are working in. For example an interface should not have method names that only covers a single problem domain even though we only currently implement a solution for this one domain, if its abstraction level justifies covering multiple problem domains.