Every piece of knowledge must have a single, unambiguous, authoritative representation within a system – Andrew Hunt, Dave Thomas
There could be scenario’s when the Project Specifications or the technology limitations imposes duplication on the development team. Such scenarios are hard to tackle and the near perfect solution would be localize the impact of violation.
This kind of duplication involves scenario when the developer doesn’t realize they are guilty of duplication. This could be resultant of a rather imperfect design.
This is the most avoidable of the four categories of duplication and describes the scenarios when the developers are lazy or pressurized with deadlines, and end up finding shortcuts via duplicating. However, the develop team as a whole needs to remember that this tiny shortcut could lead to catastrophic impacts in latter stages of project
Most commonly seen in large disconnected teams and possibly the hardest to detect. The developer in one sub team could duplicate a functionality which was already developed.
Command Query Separation
// Queries PersonInfo GetUserDetails(int userId); // Command void UpdateUserName(int userId, string userName);
Stack sampleStack = new Stack(); sampleStack.Push("DummyDataString"); var fromStack = Test.Pop();<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>
We developers have a common problem – We tend to overthink and over engineer. We tend to over think into the future attempting to foresee some of the features that we might require in the project. But most often than not, those features might require a lot of changes resulting in technical debt, or not used at all.
This is the issue YAGNI or You Aren’t Gonna Need It intends to resolve. The YAGNI Principle states that we should implement features only when we actually need them, and never when we foresee that we might need them.
YAGNI is the crux behind XP’s (Extreme Programming) Practice of “Do the simplest thing that could work” and Emergent Design which encourages developers to design only for the features that is actually needed, unlike Big Design Up Front (BDFU). This reduces a large amount of unwanted work, and avoids feature creep, resulting in avoiding cost of delay.
Think about it, if you are including features that you don’t require now, there is additional cost of delay due to additional development and testing. And to think you might never actually need that code might have you banging your head cursing your assumptions which resulted in writing the code.
YAGNI discourages developers to work on features based on assumptions that you might require it later on. In fact, YAGNI aligns with the Occam’s Razor (modern interpretation for Software Development) which states among competing hypothesis, choose one with the least assumptions. This is what Lean Software Development teaches us as well, to delay the decision making as much as possible so that decisions can be made based on facts rather than assumptions.
There are 3 keys ways a developer usually approaches error handling in code.
- Fail Safe
- Fail Fast
We have, at different point of writing code, used all three approaches. There are times when have good reasons to ignore a particular exception scenario, while at other times, we are opt for Fail Safe approach.
Fail Safe approach never hides the exception, but rather, delays it until it is safe to raise it. This is a reasonable approach, considering we are now swallowing an exception. But there is a huge problem with this approach. Most often than not, the Fail Safe approach makes the application to fail slowly, resulting in the system to continue working smoothly when the exception occurs and then fail later on. This, as a developer, inevitably leads you to spending hours debugging your code to trace a bug. What would have been a better approach ?
Fail Fast Principle
Fail Fast Principle that has its heart in Defensive Programming, encourage developers to fail fast and visibly when an exception occurs. The biggest benefit of this approach is a faster feedback loop. In early days of adhering to this principle, you might end with a lot frustrating moments as you might think your have build a fragile software, but remember, it is always better to fix the bugs upfront, than to have the customer face them. The Fast Fail Principle does exactly that for you and aids you in building a robust application.
That doesn’t mean that you should completely ignore the first two approaches. This is the guidelines I keep for myself.
- Use Ignore, only when having really specific reasons.
- Use Fast Safe, when it is a critical piece of code, and Failing Safe is a better approach
- Any other times, Use Fail Fast.
Have been thinking about putting together a collection of Jump Start Tutorials on some core concepts on Programming, finally getting everything together
- GOF: Adapter Pattern
- GOF: Strategy Pattern
- GOF: Singleton Pattern (Lazy)
- GOF: Fascade Pattern
- GOF: Chain Of Responsibility Pattern (CoR)
- GOF: Template Method
- GOF: Null Object Pattern
- GOF: State Pattern
- GOF: Decorator Pattern
- GOF: Prototype Pattern
- GOF: Bridge Pattern
- GOF: Memento Pattern
- GOF: Composite Pattern
- GOF: Observer Pattern
- Event Aggregator
- Stairway Pattern
- SOLID : Single Responsibility Principle
- SOLID : Open Closed Principle
- SOLID : Liskov Substitution Principle (Part 1)
- SOLID : Liskov Substitution Principle (Part 2)
- SOLID : Interface Segregation Principle
- Fail Fast Principle
- YAGNI Principle
- Command Query Separation (CQS) Principle
- DRY Principle
- Law of Demeter
Code Smells and Refactoring Techniques
The Open / Closed Principle focuses on one basic requirement, the classes should be Open for extensions, but closed for modification.
The better way to explain the principle would be to first express the issue in hand. Consider the below class.
The class itself looks good, but what if in future one needs to add another Shape, say Circle. This would raise need to modify our existing class which is violation of OCP.
The solution to problem lies in achieving extension by deriving from abstraction. Let’s rewrite the code.
As you can see in the above implementation, we have created an abstract class with the function we might require extension. The corresponding classes, Square and Circle, implement this abstract class and extend its functionality. So when the requirements changes, and you need to extend, you needn’t change the existing classes. This means the classes which are properly tested needn’t be touched again and thereby reduce chances of introducing bugs in existing classes.
The Chain Of Responsibility Pattern is yet another way of achieving Open Closed Principle