Assessments

Chapter 1

  1. One outcome of bad code is that you can end up with a really badly written piece of code that is hard to understand. This can often lead to programmer stress and software that is buggy, hard to maintain, and hard to test and extend.
  2. One outcome of good code is that it is easy to read and understand, as you know the programmer's intent. This leads to less stress for programmers who must debug the code, test it, and extend it.
  3. When you break a large project up into modular components and libraries, each module can be worked on by separate teams concurrently. Small modules are easy to test, code, document, deploy, extend, and maintain.
  4. DRY stands for Don't Repeat Yourself. Look for repeatable code, and refactor it so that you remove duplicate code. The advantage of this is smaller programs, because if such code contains bugs, you only have to change it in one place.
  5. KISS means simple code that will not confuse programmers, especially if you have juniors on your team. KISS code is easy to read and write tests for.
  6. S is the Single Responsibility Principle, O is the Open/Closed Principle, L is Liskov Substitution, I is the Interface Segregation Principle, and D is the Dependency Inversion Principle.
  7. YAGNI is short for You Aren't Going to Need It. In other words, don't add code you don't need. Only add the code you absolutely need, and no more.
  8. Occam's Razor is the principle that states: Entities must not be multiplied without necessity.Deal only in facts. Only make assumptions if absolutely necessary.

Chapter 2

  1. The two roles in the peer code review are reviewer and reviewee.
  2. The project manager agrees on the people that will be involved in the peer code review.
  1. You can save your reviewer time and effort prior to requesting a peer code review by making sure your code and tests all work, that you perform code analysis on your project and fix any issues raised, and that your code adheres to the company coding guidelines.
  2. When reviewing code, look out for naming, formatting, programming styles, potential bugs, correctness of code and tests, security, and performance issues.
  3. The three categories of feedback are positive, optional, and critical.

Chapter 3

  1. We can place our code in individual source files in folder structures and wrap classes, interfaces, structs, and enums in namespaces that map to the folder structure.
  2. A class should have only one responsibility.
  3. You can comment in your code for document generators using XML comments placed directly above the public member to be documented.
  4. Cohesion is the logical grouping together of code that works on the same responsibility.
  5. Coupling refers to the dependencies between classes.
  6. Cohesion should be high.
  7. Coupling should be low.
  8. You can use DI and IoC to design for change.
  9. DI stands for Dependency Injection.
  10. IoC stands for Inversion of Control.
  11. Immutable objects are type-safe and so can be safely passed between threads.
  12. Objects should expose methods and properties and hide data.
  13. Data structures should expose data and have no methods.

Chapter 4

  1. Methods with no parameters are called niladic methods.
  2. Methods with only one parameter are called monadic methods.
  3. Methods with two parameters are called dyadic methods.
  4. Methods with three parameters are called triadic methods.
  1. Methods with more than three parameters are called polyadic methods.
  2. You should avoid duplicate code. It is not a productive way to program, can make programs unnecessarily large, and has the propensity to proliferate the same exception throughout your codebase.
  3. Functional programming is a software coding methodology that treats computations as the mathematical evaluation of computations that does not modify state.
  4. The advantages of functional programming include safe code in multithreaded applications and smaller, more meaningful methods that are easy to read and understand.
  5. Input and output can be a problem for functional programs as it relies on side-effects. Functional programming does not allow for side-effects.
  6. WET code is the opposite of DRY in that code is written each time it is needed. This produces duplication, and the same exception can occur in multiple locations within a program, making maintenance and support more difficult.
  7. DRY code is the opposite of WET in that code is only ever written once and is reused wherever it is needed. This reduces the code base and exception footprint, thus making programs easier to read and maintain.
  8. You DRY out WET code by removing duplicate code using refactoring.
  9. Long methods are cumbersome and prone to exceptions. The smaller they are, the easier they are to read and maintain. There is also less chance of the programmer introducing bugs, especially of a logical nature.
  10. To avoid having to use try/catch blocks, you can write argument validators. You would then call the validators at the top of your method. If the parameters fail validation, then the appropriate exception is thrown, and the method is not executed.

Chapter 5

  1. A checked exception is an exception that is checked at compile time.
  2. An unchecked exception is an exception that is not checked or simply ignored at compile time.
  3. An overflow exception is raised when high-order bits cannot be assigned to the destination type. In checked mode, OverflowException is raised. In unchecked mode, high-order bits that cannot be assigned are simply ignored.
  4. An attempt made to access a property or a method on a null object.
  1. Implement a Validator class and an Attribute class that checks the parameter for null, and that throws ArgumentNullException. You would use the Validator class at the top of your methods so that you don't get halfway through the method before the exception is raised.
  2. Business Rule Exception (BRE).
  3. BREs are bad practice because they expect exceptions to be raised in order to control program flow.
  4. Correct programming should never control the flow of a computer program by expecting exceptions as output. So, given that BREs are bad as they expect exceptional output and use it to control program flow, a better solution is to use conditional programming. With a conditional program, you use Boolean logic. Boolean logic allows for two possible paths of execution, and never raises exceptions. Conditional checks are explicit and make the programs easier to read and maintain. You can also easily extend such code, whereas with BREs, you can't.
  5. First, start with error trapping for known types of exceptions such as ArgumentNullExceptions and OverflowExceptions using known exception types in the Microsoft .NET Framework. But when these are insufficient and don't provide enough data for your particular situation, then you would write and use your own custom exceptions and apply meaningful exception messages.
  6. Your custom exception must inherit from System.Exception, and implement three constructors: the default construct, a constructor that accepts a text message, and a constructor that accepts a text message and an inner exception.

Chapter 6

  1. A good unit test must be atomic, deterministic, repeatable, and fast.
  2. A good unit test must not be inconclusive.
  3. Test-driven development.
  4. Behavioral-driven development.
  5. A small unit of code whose only purpose is to test a single unit of code that only does one thing.
  6. A fake object used by the unit test to test the public methods and properties of a real object, but without testing the method or property dependencies.
  7. A fake object is the same as a mock object.
  8. MSTest, NUnit, and xUnit.
  1. Rhino Mocks and Moq.
  2. SpecFlow.
  3. Unnecessary comments, dead code, and redundant tests.

Chapter 7

  1. The testing of a complete system from end to end. This can be performed manually, automatically, or by using both methods.
  2. Integration testing.
  3. Manual testing of all features, all our unit tests should pass, and we should write automation tests to test the commands and data that are passed between two modules.
  4. Factories are classes that implement the factory method pattern whose intention is to allow the creation of objects without specifying their classes. We would use them in the following scenarios:
    1. The class is unable to anticipate the type of object that must be instantiated.
    2. The subclass must specify the type of object to instantiate.
    3. The class controls the instantiation of its objects.
  5. DI is a method of producing loosely coupled code that is easy to maintain and extend.
  6. Using a container makes the management of dependency objects easy.

Chapter 8

  1. A thread is a process.
  2. One.
  3. Background threads and foreground threads.
  4. The background thread.
  5. The foreground thread.
  6. Thread.Sleep(500);
  7. var thread = new Thread(Method1);
  1. Set IsBackground equal to true.
  2. A deadlock is a situation when two threads are blocked and waiting on the other thread to release the resource.
  3. Monitor.Exit(objectName);
  4. Multiple threads using the same resource generate different outputs based on the timings of each thread.
  5. Use the TPL with ContinueWith(), and use Wait() to wait until the task has finished before exiting the method.
  6. Using a member variable that is shared by other methods, and passing in reference variables.
  7. Yes.
  8. The ThreadPool.
  9. It is an object that cannot be modified once it has been constructed.
  10. They allow you to safely share data between threads.

Chapter 9

  1. Application Programming Interface.
  2. Representational State Transfer.
  3. Uniform interface, client-server, stateless, cacheable, layered system, optional executable code.
  4. Hypermedia as the Engine of Application State (HATEOAS).
  5. RapidApi.com.
  6. Authorization and authentication.
  7. Claims are statements that an entity makes about itself. These claims are then validated against a data store. They are particularly useful in role-based security to check whether the entity making the claim is authorized in regard to that claim.
  8. Making API requests and examining their responses.
  9. Because you can change your data store in keeping with your requirements.

Chapter 10

  1. The correct partitioning of software into logical namespaces, interfaces, and classes, which aids the testing of software.
  2. By understanding APIs, you can KISS your code and keep it DRY by not reinventing the wheel and writing code that already exists. This saves time, energy, and money.
  3. Structs.
  4. Third-party APIs are written by software developers, and so subject to human error that introduces bugs. By testing third-party APIs, you can be confident they work as expected, and if not, then you can have the code fixed or write a wrapper for it.
  5. Your APIs are prone to errors. By testing them in keeping with the specification and its acceptance criteria, you can be sure you are delivering what the business wants at the agreed level of quality ready for public release.
  6. The specification and acceptance criteria provide the normal program flow. From them, you can determine what to test in regard to the normal flow of execution, and you can determine what exceptional circumstances will be encountered and test for them.
  7. Namespaces, interfaces, and classes.

Chapter 11

  1. Cross-cutting concerns are those concerns that not part of the business requirements that form the core concerns, but that must be addressed in all areas of the code. AOP stands for Aspect-Oriented Programming.
  2. An aspect is an attribute that, when applied to a class, method, property, or parameter, injects code at compile time. You apply an aspect in square brackets before the item it is being applied to.
  3. An attribute gives semantic meaning to an item. You apply an attribute in square brackets before the item it is being applied to.
  4. Attributes give the code semantic meaning, while aspects remove the boilerplate code so that it is injected at compile time.
  5. When the code is being built, the compiler will insert the boilerplate code that the aspect hides from the programmer. This process is known as code weaving.

Chapter 12

  1. Code metrics are several source code measurements that enable us to identify how complex our software is, and how maintainable it is. Such measurements enable us to identify areas of code that can be made less complex and more maintainable through refactoring.
  2. Cyclomatic complexity, maintainability index, depth of inheritance, class coupling, lines of source code, and lines of executable code.
  3. Code analysis is the static analysis of source code with the intention of identifying design flaws, issues with globalization, security problems, issues with performance, and interoperability problems.
  4. Quick actions are single commands identified by a screwdriver or lightbulb that will suppress warnings, add using statements, import missing libraries and add the using statements, correct errors, and implement language usage improvements aimed at simplifying code and reducing the number of lines in a method.
  5. JetBrains' dotTrace utility is a profiling tool used for the purpose of profiling source code and compiled assemblies to identify potential issues with the software. With it you can perform sampling, tracing, line-by-line, and timeline profiling. You can profile execution time, thread time, real-time CPU instructions, and thread cycle time.
  6. JetBrains' ReSharper utility is a code refactoring tool that helps developers identify and fix code issues and implement language features to improve and speed up the programmer's programming experience.
  7. The decompilation of source code can be used to retrieve lost source code, generate PDBs for debugging, and for learning. You can also use the decompiler to see how well you have obfuscated your code to make it hard for hackers and other people to steal your code secrets.

Chapter 13

  1. Application-level, class-level, and method-level.
  2. Boolean blindness, combinatorial explosion, contrived complexity, data clump, deodorant comments, duplicate code, lost intent, mutation of variables, oddball solution, shotgun surgery, solution sprawl, and uncontrolled side effects.
  1. Cyclomatic complexity, divergent change, downcasting, excessive literal use, feature envy, inappropriate intimacy, indecent exposure, large class (also known as God object), lazy class (also known as freeloader and lazy object), middleman class, an orphan class of variables and constants, primitive obsession, refused bequest, speculative generality, Tell, don't ask!, and temporary field.
  2. Black sheep, cyclomatic complexity, contrived complexity, dead code, excessive data return, feature envy, identifier size, inappropriate intimacy, long line aka God line, lazy method, long method (God method), long parameter list (too many parameters), message chains, middleman method, oddball solutions, and speculative generality.
  3. Use LINQ instead of loops. Make classes responsible for only one thing. Make methods do only one thing. Replace long lists of parameters with parameter objects. Use creational design patterns to improve the efficiency of expensive object creation and utilization. Keep methods to 10 lines or less. Use AOP to remove boilerplate code from methods. Decouple objects and make them testable. Make code highly cohesive.
  4. A value that represents the amount of branching and looping.
  5. Reduce the amount of branching and looping that takes place until such time as the cyclomatic complexity value becomes 10 or less.
  6. Making things more complicated than they need to be.
  7. Keep It Simple, Stupid (KISS).
  8. The same thing is done by different methods with different parameter combinations.
  9. Create generic methods that can perform the same task on the different data types so that you only have the one method with one set of parameters.
  10. Fix the bad code and remove the comment.
  11. Ask for help.
  12. Stack Overflow.
  13. A long parameter list can be replaced with a parameter object.
  14. Refactor it into smaller methods that do only one thing, and remove boilerplate code into aspects using AOP.
  15. No more than 10 lines.
  16. 0-10; anything beyond that and you are asking for trouble.
  17. One.
  18. Variables, classes, properties, and methods that are not used. Get rid of them.
  19. Choose the best method of implementation, and then refactor the code to use just that method of implementation.
  1. Refactor the temporary field and the methods that operate on it into their own class.
  2. The same set of variables used in different classes. Refactor the variables into a class of their own, and then reference the class.
  3. A class inherits from another class but does not use all its methods.
  4. The Law of Demeter.
  5. Only allow classes to speak to their immediate neighbors.
  6. A class or method spending too much time inside another class or method.
  7. Refactor dependencies in their own class or method.
  8. The factory method.
  9. Inherit from a base class, and then create the new class that inherits from the base.
  10. Single responsibility is implemented in different methods of different classes across different layers of the application. Refactor the responsibility into its own class so that it is only in a single location.
  11. The data should be placed in the same object that operates on it.
  12. When you create an object that asks another object for data so that it can perform operations on it.
  13. A single change requires changes in multiple locations. Remove duplication, remove the coupling, and improve cohesion.
  14. Lost intent is when the reason for the class or method is unclear because there are lots of unrelated items clumped together. Refactor the code so that all methods are in the right class. That way, the intent of the class and the methods becomes clear.
  15. You can refactor loops with LINQ queries. LINQ is a functional language that does not alter location variables and can perform much faster than loops.

Chapter 14

  1. GoF is short for Gang-of-Four patterns. These are 23 patterns that are grouped into creational, structural, and behavioral design patterns. They are considered the foundation of all software design patterns. They work together to produce clean object-oriented code.
  2. Creational patterns enable abstraction and inheritance to provide an object-oriented way of removing code duplication and improving performance when object creation is expensive. The creational patterns are abstract factory, factory method, singleton, prototype, and builder.
  1. Structural patterns enable the correct management of relationships between objects. We can use structural patterns to enable incompatible interfaces to work together, decouple abstractions from their implementations, and improve performance. The structural patterns are adapter, bridge, composite, decorator, façade, flyweight, and proxy.
  2. Behavioral patterns govern how objects interact and communicate with each other. We can use them to produce pipelines, encapsulate commands and information to be executed at a future point in time, mediate between objects, observe state changes in objects, and more. The behavior patterns are chain of responsibility, command, interpreter, iterator, mediator, memento, observer, state, strategy, template method, and visitor.
  3. Yes.
  4. The singleton only allows a single instance of an object throughout the lifetime of the application. The object is globally accessible to all objects that need it. We use this pattern when we need to ensure we have one centralized point of object creation and object access.
  5. We use factory methods when we have a need to create objects without specifying the exact class to be instantiated.
  6. Façade.
  7. Use the flyweight design pattern.
  8. Bridge.
  9. Use the builder pattern.
  10. You would use the chain of responsibility pattern, as you can have a pipeline of handlers, each of which performs a task. If they are unable to handle the task, the handlers pass the task to their successor to handle.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.153.38