Perfect Code
-
Upload
artem-tabalin -
Category
Software
-
view
2.992 -
download
0
description
Transcript of Perfect Code
![Page 1: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/1.jpg)
Perfect Code!How to write high-quality code!
ARTEM TABALIN!
![Page 2: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/2.jpg)
Motivation!Why should we always improve our code?!Why code that just works is not enough? !
![Page 3: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/3.jpg)
Code Quality Control Law !
Improving code quality reduces development costs!
Why?!
Developer average productivity is!10-50 lines per day!
Writing code – 10%!Reading code, testing, debugging – 90%!
!
![Page 4: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/4.jpg)
Productivity vs Time!
Time
Pro
du
ctiv
ity
Productivity decreases with entropy increasing!
![Page 5: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/5.jpg)
Software Development Paradox!
1. Low-quality code slows down development!
2. Devs reduce code quality to meet a deadline!
Paradox: “Devs have no time to work rapidly”!
The clue: #2 is wrong!
Impossible to successfully meet a deadline messing up the code!
Continuously maintain high code quality!
![Page 6: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/6.jpg)
The Boy Scout Rule!
It’s not enough to write code well - prevent “rotting”!
!
“Leave the campground cleaner than you found it”!!
![Page 7: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/7.jpg)
Software Development Principles!KISS, YAGNI, DRY, SOLID!
![Page 8: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/8.jpg)
Keep Code Simple!
KISS (Keep It Simple, Stupid)!
Simplicity is a key goal!
Components should be integrated tightly or weakly (?)!
Try to reduce influence between components!
Follow “Divide and Conquer” principle!
!
![Page 9: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/9.jpg)
Division of Responsibilities!
• System → packages!
• Package → classes!
• Class → methods!
• Method → control statements!
Low coupling on each level!
![Page 10: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/10.jpg)
Use Patterns!
Don’t reinvent the square wheel!
• Reduce complexity!
• Less mistakes!
• Simplify communication!
!
Examples: Repository, Factory, Adapter, Strategy, Observer!
![Page 11: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/11.jpg)
No Unnecessary Code!
YAGNI (You Aren’t Gonna Need It)!
Implement things only when you really need them!!
![Page 12: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/12.jpg)
Avoid Duplication!
DRY (Don’t Repeat Yourself)!
!
“Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.”!
!
![Page 13: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/13.jpg)
Object-Oriented Design!
SOLID!
1. Single Responsibility (SRP)!
2. Open-Closed (OCP)!
3. Liskov Substitution (LSP)!
4. Interface Segregation (ISP)!
5. Dependency Inversion (DIP)!
![Page 14: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/14.jpg)
Single Responsibility Principle!
“A class should have one and only one reason to change”!!
![Page 15: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/15.jpg)
Open-Closed Principle!Class should be opened to extension and closed for modification!
GraphicEditor
+drawShape
Shape
+draw
Rectangle
+draw
Circle
+draw
violation +drawCircle +drawRectangle +drawTriangle
Triangle
+draw
![Page 16: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/16.jpg)
Liskov Substitution Principle!Objects implementing an interface can be used interchangeably!
!
IResizable +bounds +resize
Shape +bounds +resize
Image +bounds +resize
violation
resize(IResizable obj) {
if(obj is TextBlock)
return; obj.resize(); }
TextBlock +bounds +resize
GraphicEditor
+resize(IResizable)
![Page 17: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/17.jpg)
Interface Segregation Principle!Clients should not depend on interfaces they don’t use!
!
Shape +resize +move +select
IResizable +resize
ISelectable +select
violation
IGraphic +resize +move +select
IMovable +move
![Page 18: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/18.jpg)
Dependency Inversion Principle!Abstractions should not depend on details!
GraphicEditor
+logger: ILogger
ILogger
EmailLogger SystemLogger
violation
GraphicEditor() {
logger = new FileLogger(); }
FileLogger
![Page 19: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/19.jpg)
Meaningful Names!Naming principles. Name length. Variable names. !Class names. Method names.!
![Page 20: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/20.jpg)
Naming Principles!
Name should show your intention!
int d; // elapsed time
Is it good enough?!
Which name is better?!
int elapsedTimeInDays;
int daysSinceCreation;
!
!
!
![Page 21: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/21.jpg)
Naming Principles!What does the following code do?!
function getItems(items) { var list1 = []; for(var i = 0; i < items.length; i++) { var x = items[i]; if(items[i]["Field"] === 12) { list1.push(x); } } return list1; }
!
![Page 22: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/22.jpg)
Naming Principles!What is about this one?!
function getMarkedCells(cells) { var result = []; for(var i = 0; i < cells.length; i++) { var cell = cells[i]; if(cell.Status === CellStatus.Marked) { result.push(cell); } } return result; }
![Page 23: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/23.jpg)
Naming Principles!
No implementation details!
HashSet<Account> accountHashSet;
Is it good enough? Why?!
What if we decide to use List?!Which name is better?!
HashSet<Account> accounts;
!
![Page 24: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/24.jpg)
Naming Principles!
Choose easy-to-pronounce name!
class Cstmr { private int prsnid; private DateTime genTstmp; private DateTime modTstmp; }
class Customer { private int personId; private DateTime generationTimestamp; private DateTime modificationTimestamp;
}
!
![Page 25: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/25.jpg)
Naming Principles!
• Single word for concept (avoid synonyms)! fetch / retrieve / get controller / manager / driver!
• Names from patterns and algos! RenderStrategy, JobQueue!
• Names from user stories! Credit, Debit, Asset!
• Antonyms! begin / end first / last min / max next / previous! old / new opened / closed source / target up / down!!
![Page 26: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/26.jpg)
Naming Convention!
The most important is to follow to the convention!
Example:!• CONSTANT
• ClassName
• localVariable
• _privateMember
![Page 27: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/27.jpg)
Name Length!What is the optimal length for a name?!
x → maximumNumberOfPointsInEachLine
short / long name pros & cons!
short names – lacks of information!long names – harder to read and write!!10-16 characters is the optimal length!if < 10 ask: is meaningful enough?!if > 16 ask: isn’t verbose?!
![Page 28: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/28.jpg)
Loop Variable Names!
• Simple loop!for(int i = 0; i < data.length; i++) { data[i] = 0; }
• Complex loop!for(int teamIndex = 0; teamIndex < teamCount; teamIndex++) { for(int playerIndex = 0; playerIndex < count; playerIndex++) { playerStore[teamIndex][playerIndex] = 0; } }!
![Page 29: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/29.jpg)
Loop Variable Names!
• Variable used outside of the loop
int recordCount = 0;
while(moreRecords()) { data[recordCount] = getNextRecord(); recordCount++; }
// … recordCount is accessed here
!
![Page 30: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/30.jpg)
Temporary Variable Names!
Avoid pointless names!
temp = sqrt(b^2 -‐ 4*a*c); root[0] = (-‐b + temp) / (2*a); root[1] = (-‐b -‐ temp) / (2*a);
How to improve?!
discriminant = sqrt(b^2 -‐ 4*a*c); root[0] = (-‐b + discriminant) / (2*a); root[1] = (-‐b -‐ discriminant) / (2*a);
!
![Page 31: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/31.jpg)
Boolean Variables and Methods!
Use verbs is, has, can for booleans!
• isSupported!
• hasNext!
• canExecute!
![Page 32: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/32.jpg)
Class Names!
Use nouns and noun combinations for classes!
• Client!
• Window!
• UserAccount!
• FileLoader!
![Page 33: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/33.jpg)
Method Names!
Use verbs and verb phrases for methods!
• Save!
• Close!
• GetAccount!
• LoadFile!
![Page 34: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/34.jpg)
Variables!Declaration. Initialization. Lifetime and scope.!
![Page 35: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/35.jpg)
Declaration!
• Declare all variables!
• Turn off implicit variable declaration!
JavaScript: “use strict”
VB: Option Explicit On
php: error_reporting(E_STRICT);
!
![Page 36: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/36.jpg)
Initialization!
Initialize variables at declaration!
var total = 0;
or at first occurrence in code!
Dim total As Double ' another code total = 0.0 ' code using total
!
![Page 37: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/37.jpg)
Lifetime and Scope!
Variables lifetime and scope should be minimal!
Why?!
Does code follow the principle?!
function summarizeData() { var oldData = getOldData(); var totalOldData = summarize(oldData); printData(totalOldData); saveData(totalOldData); var newData = getNewData(); var totalNewData = summarize(newData); printData(totalNewData); saveData(totalNewData); }
![Page 38: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/38.jpg)
Lifetime and Scope!Code might look like!
function summarizeData() { var oldData = getOldData(); var newData = getNewData(); var totalOldData = summarize(oldData); var totalNewData = summarize(newData); printData(totalOldData); printData(totalNewData); saveData(totalOldData); saveData(totalNewData); }
!
!
![Page 39: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/39.jpg)
Lifetime and Scope!
• Single purpose principle!int value = getValue(); int result = calcResult(value); // some code value = val1; val1 = val2; val2 = value;
• Avoid global variables!
• Prefer the most restrictive access level! private → public!
var swap = val1; val1 = val2; val2 = swap;
→
![Page 40: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/40.jpg)
Methods (Functions)!Purposes. Principles. Order. Parameters.!
![Page 41: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/41.jpg)
Purposes!
• Simplify code !
• Improve readability !
• Documentation defines abstraction!
• Eliminating duplication most popular!
• Inheritance support method overriding!
![Page 42: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/42.jpg)
Principles!
Method should be small!
How many lines?!
not more than 20 lines and better even less!
Example:!
public ReportContainer BuildReport(IList<Order> orders) { var report = new ReportContainer(); report.Lines = BuildReportLines(orders); report.Total = BuildReportTotal(report.Lines); return report; }
!
![Page 43: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/43.jpg)
Principles!
Method should have!
• blocks (if, else, for, while) 1-3 lines long!• indent level not more than 2!
private IList<ReportLine> BuildReportLines(IList<Order> orders) { IList<ReportLine> result = new List<ReportLine>(); foreach (Order order in orders) { ReportLine reportLine = BuildReportLine(order); if (reportLine.IsVisible) result.Add(reportLine); } return result; }
!
![Page 44: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/44.jpg)
Principles!
Single Thing Rule!
Function should do one thing, do it only, and do it well!
Examples:!
• BuildReport – makes report!
• BuildReportLines – prepares report lines!
• BuildReportTotal – summarizes report!
Criteria: function cannot be divided into sections!
![Page 45: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/45.jpg)
Principles!
Single Abstraction Level!
Mixing up abstraction levels increases complexity!
Does code follow the principle? Why?!
private Report BuildReport(Order order) { var result = new Report(); result.Header = BuildReportHeader(order.Title); result.Body = ReportHelper.TextToHtml(order.Description); result.Footer = "<b>" + APP_NAME + "</b>"; result.Footer += " CopyRight © " + DateTime.Now.Year; return result; }
!
![Page 46: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/46.jpg)
Principles!Better!
private Report BuildReport(Order order) { var result = new Report(); result.Header = BuildReportHeader(order.Title); result.Body = ReportHelper.TextToHtml(order.Description); result.Footer = BuildReportFooter(); return result; }
Much Better!
private Report BuildReport(Order order) { var result = new Report(); result.Header = BuildReportHeader(order.Title); result.Body = BuildReportBody(order.Description); result.Footer = BuildReportFooter(); return result; }
!
![Page 47: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/47.jpg)
Principles!
Command-Query Separation (CQS)!
Method performs an action OR returns data!
Does code follow the principle?!
if (SetAttribute("username", "Admin")) { // code }
How to fix?
if (HasAttribute("username")) { SetAttribute("username", "Admin"); // code }
![Page 48: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/48.jpg)
Order!The Stepdown Rule!
Read code from top to bottom (by abstraction levels)!
public Report BuildReport(IList<Order> orders) { // uses BuildReportLines and BuildReportTotal } private Report BuildReportLines(IList<Order> orders) { // uses BuildReportLine } private Report BuildReportLine(IList<Order> orders) { // code } private Report BuildReportTotal(IList<Order> orders) { // code }
![Page 49: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/49.jpg)
Arguments!How many parameters should a method have?!
• Ideally 0!
• Avoid methods with more than 2 arguments!
Why?!
• Harder to read (remember passing values)!
• Increase coupling!
• Harder to test (combinatorial growth of variants)!
![Page 50: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/50.jpg)
Arguments!Avoid boolean arguments!
Why?!
• Usually can be divided into two sections!• Hard to understand a purpose of an argument!BuildReportLine(order, true);
private Report BuildReportLine(Order order, bool isMarked) { if (isMarked) { // build marked report line } else { // build simple report line } }
![Page 51: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/51.jpg)
Classes!Purposes. Principles. Interface. Encapsulation. Inheritance.!
![Page 52: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/52.jpg)
Purposes!• Simplify code
• Improve readability!
• Limit the scope of changes!
• Hide implementation details (encapsulation)!
• Allow to prepare generic solution (abstraction)!
• Eliminate duplication (delegation & inheritance)!
• Provide extensibility (inheritance)!
• Allow to work with real domain entities!
![Page 53: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/53.jpg)
Principles!
• Encapsulation! Hide as much as possible!
• Compactness! Reduce class responsibilities (SRP)!
• Abstraction! Program to an interface, not an implementation!
• High Cohesion! Fields and methods should belong together!
![Page 54: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/54.jpg)
Interface!
Methods should be on the same abstraction level!
Does code follow the principle? Why?!
class Program { public void InitializeCommandStack(); public void PushCommand(Command command); public Command PopCommand(); public void ShutdownCommandStack(); public void InitializeReportFormatting(); public void FormatReport(Report report); public void PrintReport(Report report); public void InitializeGlobalData(); public void ShutdownGlobalData(); }
![Page 55: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/55.jpg)
Interface!
Programming over semantic!
• Programming – can be checked by compiler! Amount of arguments! Argument types!
• Semantic – cannot be checked by compiler! Method A should be called after method B! Method A throws exception when argument is not initialized!!
![Page 56: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/56.jpg)
Encapsulation!
• Not public should be private ! private → public!
• No direct access to fields!private decimal _x = 0; public decimal X { get { return _x; } set { _x = value; } }
• No assumptions about class clients!// param2 should be > 0, in other case method fails public int Method(int param1, int param2)
!
![Page 57: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/57.jpg)
Inheritance!
Should be able to say that child ‘is’ parent!Circle is Shape HtmlParser is Parser!
Does code follow the principle?! class Customer { public int ID { get; set; } public string Name { get; set; } } class Bank: Customer { public string CorrespondentAccount { get; set; } }
Depends on whether a bank can be a customer or not!
!
![Page 58: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/58.jpg)
Inheritance!
Move common methods to base class!
abstract class Stream { public void Write(byte[] bytes); public byte[] Read(); } class SecureStream: Stream { public void Init(StreamConfig config); }
!
![Page 59: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/59.jpg)
Inheritance!
Avoid following situations:!
• Parent class has only one child!
• Child overrides method leaving it empty!
• Too many hierarchy levels! better not more than 3 levels!
![Page 60: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/60.jpg)
Comments!Commenting principles. Bad comments. Good comments.!
![Page 61: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/61.jpg)
Commenting Principles!
• Comments do not redress bad code! clean code much better than bad code with comments!
• Do not comment tricky code – rewrite it! tricky code = bad code!
• Try to explain with code!// is employee eligible for bonus if ((employee.Schedule == HOURLY_SCHEDULE) && employee.Age > 65) { … } !Better!
if (employee.IsEligibleForBonus()) { … }
![Page 62: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/62.jpg)
Commenting Principles!
Comment says “why” not “how”!
• How!// if flag equals to zero if (accountFlag == 0)
• Why!// if new account created if (accountFlag == 0)
• Code instead of comment!if (accountType == AccountType.NewAccount)
![Page 63: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/63.jpg)
Bad Comments!• Redundant comments! obvious and repeating code!
// closing connection Connection.Close();
• Commented code! remove unnecessary code, VCS is for the rescue
InputStream response = new InputStream(); response.SetBody(formatter.ResultStream, formatter.BytesCount); //InputStream resultStream = formatter.ResultStream; //StreamReader reader = new StreamReader(resultStream); //response.SetContent(reader.Read(formatter.BytesCount));
![Page 64: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/64.jpg)
Good Comments!• Legal comments! license, copyright, author!
• Explanations! provide info about inevitable tricks
// NOTE: postpone execution to refresh UI setTimeout(function() { // code });
• TODOs! notes for future to avoid “broken windows”
// TODO: get rid of tricky workaround function badFunction() { // tricky workaround here });
![Page 65: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/65.jpg)
Thank you!!
Your questions, please!!ARTEM TABALIN!
![Page 66: Perfect Code](https://reader034.fdocuments.net/reader034/viewer/2022052600/557d5f38d8b42abf3d8b4ff4/html5/thumbnails/66.jpg)
References!
• Steve McConnell Code Complete!
• Robert C. Martin Clean Code!
• Hunt A., Thomas D. The Pragmatic Programmer !
• Craig Larman Applying UML and Patterns!
• Kent Beck Implementation Patterns!
• Eric Evans Domain-Driven Design!