Hearted Youtube comments on Kantan Coding (@kantancoding) channel.

  1. 3200
  2. 2200
  3. 2100
  4. 827
  5. 625
  6. 531
  7. 305
  8. 281
  9. 277
  10. 268
  11. 218
  12. 217
  13. 166
  14. 162
  15. 147
  16. 146
  17. 127
  18. 114
  19. 111
  20. 108
  21. 99
  22. 93
  23. 73
  24. 72
  25. 71
  26. 69
  27. 68
  28. 67
  29. 67
  30. 66
  31. 65
  32. 64
  33. 58
  34. 58
  35. 55
  36. 53
  37. 50
  38. 48
  39. 47
  40. 47
  41. 47
  42. 46
  43. 45
  44. I really dislike the common wisdom about "self-documenting code" as it is proven again and again by examples that are the simplest of simple code. I think it all starts somewhere different. And that's the distribution of logic into multiple methods when it does not need to be that way. When ever something gets so big that you might add in a comment, someone will say "just split it into descriptive methods", and yes, in the spirit of uncle bob you can split that 30 lines method into 10 simple methods. And instead of reading the code from lines 30 to line 60, the dev now has to scroll around trying to memorize 10 methods and what they do and build a mental model of how they are called. And after splitting one method into 10 methods, it's suddenly too much work to put a doc header of them, so we don't do it because we don't like tying shit after we just split that shit up for no reason. Three steps back. Lets not split up code if there's no reusing of the methods. Let's keep the code local, in context. Complex code exists, because complicated tasks exist. So you got complex code. Your coworker asks "what dos that do?" What do say? Do you go line by line saying things like "so this line checks if the first parameter is null" and so on? Of course not. Your coworker can read. Human language can is great to explain the concept of something. You will probably be able to formulate one sentence that can explain a complex block of code. Well, if you understand that code you should. And that's a good comment. Because three years later, someone will search for a bug and will find that block of code and ONE GOOD LINE may explain it better than anything else. "So what if the comments lie?" Comments are written with the assumption that code does what it is meant to do. Comments may "lie" when the code does not what it is meant to do, but in that case, the bug is the discrepancy between intended and actual behavior. You got two versions now, one telling you what it does, and one what it is supposed to do. You can now check if the assumptions where wrong from the beginning or if it's an implementation error and the fix is going to make the code do what the comment tells. That's my experience in working with complicated code.
    44
  45. 44
  46. 44
  47. 44
  48. 41
  49. 40
  50. 39
  51. 36
  52. 36
  53. 34
  54. 34
  55. 33
  56. 32
  57. 32
  58. 31
  59. 31
  60. 31
  61. 31
  62. 30
  63. 30
  64. 29
  65. 28
  66. 27
  67. 27
  68. 27
  69. 26
  70. 25
  71. 25
  72. 24
  73. 24
  74. 24
  75. 24
  76. 23
  77. 23
  78. 22
  79. 21
  80. 21
  81. 21
  82. 20
  83. 20
  84. 19
  85. 19
  86. 18
  87. The long names for tests are actually pretty standard. It's not so much about the long name as it is about documentation. A well-tested code-base can contain thousands or even tens of thousands of tests and when the business logic becomes a bit more intricate than these examples you can have multiple failed tests for one seemingly simple change. Being able to read through the test names and understand what their testing without opening each one up to read comments or the code itself saves a lot of time and keeps you from getting distracted from your actual goal of fixing your regression. Another reason for verbose test names is that a test tends to be more granular than a method would normally be. You could potentially test 10 outcomes for one, let's say 10 line method. To use one of the tests in the video as an example: 'TestIsBlankStringShouldReturnTrueWhenBlank 'could be shortened to something like 'TestIsBlank'. This would work fine in the video because it's just used as an example, but you would normally test more than just the one outcome. You'd need to test that the method behaves correctly if a null value is passed in or that it does, in fact, return false if the string is not blank and not true as well. Never mind languages that don't have type safety like javascript where you'd have to check if the method handles integers correctly. What would you call the methods for these tests, considering that 'TestIsBlank' is already in use? With that said, most test frameworks have a some sort of description feature that would display the description instead of the test name in the test-runner. The descriptions act as a sort of comment. Sorry for the essay, but there are a lot of intricacies in writing maintainable tests and rather specific reasons for things that look arbitrary or unnecessary. Much like test names, the explanation as to why they are long is also, well, long.
    18
  88. 18
  89. 18
  90. 18
  91. 18
  92. 18
  93. 17
  94. 17
  95. 17
  96. 17
  97. 17
  98. 17
  99. 17
  100. 16
  101. 16
  102. 16
  103. 16
  104. 16
  105. 16
  106. 16
  107. 15
  108. 15
  109. 15
  110. 14
  111. 14
  112. 14
  113. 14
  114. 14
  115. 14
  116. 14
  117. 14
  118. 14
  119. 13
  120. 13
  121. 13
  122. 13
  123. 13
  124. 13
  125. 13
  126. 13
  127. 12
  128. 12
  129. 12
  130. 12
  131. 12
  132. 11
  133. 11
  134. 11
  135. 11
  136. 11
  137. 10
  138. 10
  139. 10
  140. 10
  141. 10
  142. 10
  143. 10
  144. 9
  145. 9
  146. 9
  147. 9
  148. 9
  149. 9
  150. 9
  151. 9
  152. 9
  153. 9
  154. 8
  155.  @kantancoding  What I was saying is that comments provide "a" layer of guidance and confirmation, not "the" confirmation. Yes certainly, there should be test cases. But in practical terms, the struggles around not knowing which is wrong, the code or the comments/tests is still valid in both paradigms, whether you're taking about comments or tests cases. Either way, when the bug report comes in, someone has to find the bug. When reading that code and wondering "hmm is this < supposed to be a <=", or "is this parentheses misplaced", or "is this parameter wrong", its much, much easier to read the nearby comments and gather the intent than to flip back and forth to another file elsewhere (like a test case) to try to figure out what the commentless "self documenting" code was supposed to do. The part about "self documenting code can eliminate the need for most comments" is the fallacy. Sure, when you're the one writing the code, your own comments can look somewhat redundant. But that's cognitive bias coming from already understanding the code and whatever idea it was implementing. To someone else debugging that code their first time, those comments can be valuable. The bandwagon of "self documenting code" and pressure to comment less seems to keep coming up as if its an answer, but it isn't. It's part of the problem, and its bad. Just like a dev who doesn't update comments is bad. I don't make excuses for either of them. You are right in that comments can be poorly written. Writing good comments is a skill, just like coding itself is a skill. But someone else's poorly written comments aren't a validation to this movement of discouraging comments in the name of "self documentation".
    8
  156. 8
  157. 8
  158. 8
  159. 8
  160. 8
  161. 8
  162. 8
  163. 8
  164. 8
  165. 7
  166. 7
  167. 7
  168. 7
  169. 7
  170. 7
  171. 7
  172. 7
  173. 7
  174. 7
  175. 7
  176. 7
  177. 7
  178. 7
  179. 7
  180. 7
  181. 6
  182. 6
  183. 6
  184. I really need to say this. The advice to never nest your code has been repeated for years now, it's the same thing that I was told 8 years ago when I was reading about how to write VB code in highschool and it is a good concept, but It's important to note something. In the provided example, yes, I think the code is easier to read, but it does not change the conditions you need to keep in your head. If you are doing more complex logic that then relies on the state of those conditions, you still need to know that those conditions are not true for example. Take authentication. If you have middleware the runs in an endpoint, or your function verifies that the user is authenticated before running, you still need to know that condition has been met, otherwise you will end up writing redundant code in your actual logic to ensure that the user is authenticated. Whether your nest or don't nest the condition, you need to be aware of the state your app can be in at that point in the code, and both ways require you to have this awareness. I agree that in most cases, early returns are better, but just wait until you have a function that has a structure like this and tell me it isn't confusing AF if (A) return // logic if (B) return if (C) return // logic if (D) { //logic } else { //logic } if (E) return //logic The code looks readable, but damn, it can get confusing, especially if the code I put as "//logic" can potentially return, therefore adding conditions that aren't even ovbious. Sometimes the real solution in my opinion is to double up your conditions just for understandings sake, or in a complex case, abstract where necessary. The idea of code inversion is very primitive and does not always apply
    6
  185. 6
  186. 6
  187. 6
  188. 6
  189. 6
  190. 6
  191. 6
  192. 6
  193. 6
  194. 6
  195. 6
  196. 6
  197. 6
  198. 6
  199. 6
  200. 6
  201. 6
  202. 6
  203. 6
  204. 6
  205. 6
  206. 6
  207. 6
  208. 6
  209. 5
  210. 5
  211. 5
  212. 5
  213. 5
  214. 5
  215. 5
  216. 5
  217. 5
  218. 5
  219. 5
  220. 5
  221. 5
  222. 5
  223. 5
  224. 5
  225. 5
  226. 5
  227. 5
  228. 5
  229. 5
  230. 5
  231. 5
  232. 5
  233. 5
  234. 5
  235. 5
  236. 5
  237. 5
  238. 5
  239. 5
  240. 5
  241. 5
  242. 5
  243. 5
  244. 5
  245. 5
  246. 5
  247. 5
  248. 5
  249. 4
  250. 4
  251. 4
  252. 4
  253. 4
  254. 4
  255. 4
  256. 4
  257. 4
  258. 4
  259. 4
  260. 4
  261. 4
  262. 4
  263. 4
  264. 4
  265. 4
  266. 4
  267. 4
  268. 4
  269. 4
  270. 4
  271. 4
  272. 4
  273. 4
  274. 4
  275. 4
  276. 4
  277. 4
  278. 4
  279. 4
  280. 4
  281. 4
  282. 4
  283. 4
  284. 4
  285. 4
  286. 4
  287. 4
  288. 4
  289. 4
  290. 4
  291. 4
  292. 4
  293. 4
  294. 4
  295. 4
  296. 4
  297. 4
  298. 4
  299. 4
  300. 4
  301. 4
  302. 4
  303. 4
  304. 4
  305. 4
  306. 4
  307. 4
  308. 4
  309. 4
  310. 4
  311. 4
  312. 4
  313. 4
  314. 4
  315. 4
  316. 4
  317. 4
  318. 4
  319. 4
  320. 4
  321. 4
  322. 4
  323. 4
  324. 4
  325. 3
  326. 3
  327. 3
  328. 3
  329. 3
  330. 3
  331. 3
  332. 3
  333. 3
  334. 3
  335. 3
  336. 3
  337. 3
  338. 3
  339. 3
  340. 3
  341. 3
  342. 3
  343. 3
  344. 3
  345. 3
  346. 3
  347. 3
  348. 3
  349. 3
  350. 3
  351. 3
  352. 3
  353. 3
  354. 3
  355. 3
  356. 3
  357. 3
  358. 3
  359. 3
  360. 3
  361. 3
  362. 3
  363. 3
  364. 3
  365. 3
  366. 3
  367. 3
  368. 3
  369. 3
  370. 3
  371. 3
  372. 3
  373. 3
  374. 3
  375. 3
  376. 3
  377. 3
  378. 3
  379. 3
  380. 3
  381. 3
  382. 3
  383. 3
  384. 3
  385. 3
  386. 3
  387. 3
  388. 3
  389. 3
  390. 3
  391. 3
  392. 3
  393. 3
  394. 3
  395. 3
  396. 3
  397. 3
  398. 3
  399. 3
  400. 3
  401. 3
  402. 3
  403. 3
  404. 3
  405. 3
  406. 3
  407. 3
  408. 3
  409. 3
  410. 3
  411. 3
  412. 3
  413. 3
  414. 3
  415. 3
  416. 3
  417. 3
  418. 3
  419. 3
  420. 3
  421. 3
  422. 3
  423. 3
  424. 3
  425. 3
  426. 3
  427. 3
  428. 3
  429. 3
  430. 3
  431. 3
  432. 3
  433. 3
  434. 3
  435. 3
  436. 3
  437. 3
  438. 3
  439. 3
  440. 3
  441. 3
  442. 3
  443. 3
  444. 3
  445. 3
  446. 3
  447. 3
  448. 3
  449. 3
  450. 3
  451. 3
  452. 3
  453. 3
  454. 3
  455. 3
  456. 3
  457. 3
  458. 3
  459. 3
  460. 3
  461. 3
  462. 3
  463. 3
  464. 3
  465. 3
  466. 3
  467. 3
  468. 3
  469. 3
  470. 3
  471. 3
  472. 3
  473. 3
  474. 3
  475. 3
  476. 3
  477. 3
  478. 3
  479. 3
  480. 2
  481. 2
  482. 2
  483. 2
  484. 2
  485. 2
  486. 2
  487. 2
  488. 2
  489. 2
  490. 2
  491. 2
  492. 2
  493. 2
  494. 2
  495. 2
  496. 2
  497. 2
  498. 2
  499. 2
  500. 2
  501. 2
  502. 2
  503. 2
  504. 2
  505. 2
  506. 2
  507. 2
  508. 2
  509. 2
  510. 2
  511. 2
  512. 2
  513. 2
  514. 2
  515. 2
  516. 2
  517. 2
  518. 2
  519. 2
  520. 2
  521. 2
  522. 2
  523. 2
  524. 2
  525. 2
  526. 2
  527. 2
  528. 2
  529. 2
  530. 2
  531. 2
  532. 2
  533. 2
  534. 2
  535. 2
  536. 2
  537. 2
  538. 2
  539. 2
  540. 2
  541. 2
  542. 2
  543. 2
  544. 2
  545. 2
  546. 2
  547. 2
  548. 2
  549. 2
  550. 2
  551. 2
  552. 2
  553. 2
  554. 2
  555. 2
  556. 2
  557. 2
  558. First 5 seconds is dead wrong. Some of the best developers in the world nest their code several layers deep. Why? Because that gives the best performance, and is often the easiest thing to understand and refactor, especially in early stages of development. You know what's difficult to reason about? Inheritance and prematurely encapsulated logic - which is often promoted as the remedy. But it's okay (and expected) to not be able to reason about nested code (or large amounts of code in general) at first, and wanting to extract snippets to something that gives you more mental clarity. Just know that it's not categorically better to avoid it - it's situational and depends on the experience of the team. 0:32 And as far as inverting the if statements go, that is just as easy for me to reason about, as someone with a decade of experience. The main difference is that now the unlikely error states takes precedence in the function, and most times I need to read the typical cases. Which means I can now see less of the real meat of the function while also seeing the useful summarizing function name. It's a minor difference, but I think there's good reasons to disagree with your statement here. 2:13 There's no way that's a confusing if-statement, unless you're an absolute beginner. The good variable names give it all away. The only way it would be confusing to me is if those variables had ambiguous names. Extracting it to a function suddenly makes it a non-zero risk that the function is doing something unpredictable (unless it's guaranteed to be a pure function), so when debugging it, you now have to navigate to the isValidUser function to verify that it doesn't, which results in additional cognitive load, not less. But the calculateTaxes() example is not the worst. Except I think the entire "main" function there seems to be the function that should be called calculateTaxesForCart() so there should be no further clarity needed - especially not for such a small function. 4:05 It's not the best example, because it's really slow to do a list of single user queries if they're not cached. Batching is always better. But if we ignore that part, I think you're missing the essential guidance of when to make something reusable. Because premature reusability is a common source of a wasted effort for developers. And the answer is: wait until you have actually done the identical logic two places in your code. And three or four times if it's something fairly simple. And note that if the function is not pure (i.e. giving it the same parameter values can yield different results), then it's harder to reuse safely unless the function's purpose is abundantly clear. 4:38 I categorically agree with good naming, but I'd go further and say that it's better to error on very long names to clear up any ambiguity. The only good reason to shorten names is if you're creating a temporary alias shorthand for quickly modifying a complicated algorithm over many iterations. Some experience developers also think it's okay to mirror the mathematical letters in the paper of an algorithm that was applied, but I personally disagree and think you could add those as comments instead. Naming can be really hard, but it's a vital skill to keep practicing as a programmer, because six months after writing the code, you'll also find that even you don't understand your own low-effort-naming very easily. Additionally, even absolute beginners probably realized quickly that naming was important, so I think it's more useful to provide more clarification and examples than just that statement. Lastly, these are not remotely "laws" - and that term is preached far too often within developer circles. I think the only thing that approximates an actual law in computer science, is Conway's Law. I.e. that the structure of the software strongly correlates with the structure of the team(s) that built it.
    2
  559. 2
  560. 2
  561. 2
  562. 2
  563. 2
  564. 2
  565. 2
  566. 2
  567. 2
  568. 2
  569. 2
  570. 2
  571. 2
  572. 2
  573. 2
  574. 2
  575. 2
  576. 2
  577. 2
  578. 2
  579. 2
  580. 2
  581. 2
  582. Readable code, schmedable code. Make updated comments a requirement before code gets merged. Yes, comments can lie, but so can variable names, which objectively are just memory addresses with built-in comments. Their names are not for the computer, they are for you the developer. Make comment changes part of code review. You could create a function just like the one at the beginning, but if there is no circle that needs it's area calculated but some thing else that has a virtually identical formula, is the code really self-documenting? If we are okay with updating variable and function names, updating comments should be no different. Ontop of that, If I have a game that has 30 enemy types, and each attack pattern is created by a function, should I change each function name to "consecutiveNormalPunchesAttack" or "falconSmashAttack"? What if each has to conform to an interface? Should I make a private function that has the sole purpose of documenting what the attack is supposed to be like? Perhaps if there is some extra special logic, such as randomly chosen attacks that each have their own complex logic, but if I have a 20 simple enemies that basically have only simple but unique attack function, I think making extra and redundant functions is only going to make a file longer, bloated, and harder to follow. I'd rather have a clear comment that explains what the code is supposed to do, which is what the real purpose of comments is. It isn't about what the code does, it's why it's there.
    2
  583. 2
  584. 2
  585. 2
  586. 2
  587. 2
  588. 2
  589. 2
  590. 2
  591. 2
  592. 2
  593. 2
  594. 2
  595. 2
  596. 2
  597. 2
  598. 2
  599. 2
  600. 2
  601. 2
  602. 2
  603. 2
  604. 2
  605. 2
  606. 2
  607. 2
  608. 2
  609. 2
  610. 2
  611. 2
  612. 2
  613. 2
  614. 2
  615. 2
  616. 2
  617. 2
  618. 2
  619. 2
  620. 2
  621. 2
  622. 2
  623. 2
  624. 2
  625. 2
  626. 2
  627. 2
  628. 2
  629. 2
  630. 2
  631. 2
  632. 2
  633. 2
  634. 2
  635. 2
  636. 2
  637. 2
  638. 2
  639. 2
  640. 2
  641. 2
  642. 2
  643. 2
  644. ​ @kantancoding  hey I appreciate the response! And I hope I'm coming across as helpful not just negative! I've extensive experience teaching junior engineers, and like you say the senior engineer understands what you're saying and can contextualise it. The junior engineers cannot, and so what I mean to say is the examples given can lead people astray. Dependency Injection would absolutely make that code modular in the way it was split - I might be wrong but I don't think DI was mentioned in the video, and this is a key detail here that is often not obvious to juniors. A similar detail that can cause a misconception is avoiding hard coding the company by extracting to a constant, but the constant is still hard coded - it's just not inside the function any more. Similar to just moving code into another function does not produce modularity, moving a literal to a constant does not remove hard coding. Again, a senior gets that but a junior might not. Unit testing against a public interface is more than my opinion, it's more or less the only way that unit testing is generally useful 😅 you can test implementation details if you like but you'll just end up writing your code twice every time, which is where many people go wrong with TDD and end up jaded on it. You want to treat your code as a black box, and only this will produce the very real and very powerful positive outcomes you mention in your video. Public in this sense means where the "seams" in your code are, in other words the public edges of your abstractions. Usually in C# or Java worlds this is an interface, in JavaScript it would be an exported function. If you are exporting a function, or promoting a class member above private just so that your unit tests can see it, this is often an indication that you're testing implementation details. When you decide what a piece of code does, you encode its contract with the world in the tests you write against it. The tests (like you very rightly pointed out!) then form machine verifiable documentation to others about how to use the code and what it does and does not do. So in that sense what we mean by public here is what does a caller need to know and care about, and what shouldn't they know and care about? And this is the key art of software design, i.e. choosing useful, meaningful abstractions that effectively modularise your code. I enjoy your format, and I think you're sharing really good ideas! I do think these kinds of details are important if you are aiming to teach your ideas accurately (based on my own learned experience teaching poorly on many occasions!). I hope it helps!
    2
  645. 2
  646. 2
  647. 2
  648. 2
  649. 2
  650. 2
  651. 2
  652. 2
  653. 2
  654. 2
  655. 2
  656. 2
  657. 2
  658. 2
  659. 2
  660. 2
  661. 2
  662. 2
  663. 2
  664. 2
  665. 2
  666. 2
  667. 2
  668. 2
  669. 2
  670. 2
  671. 2
  672. 2
  673. 2
  674. 2
  675. 2
  676. 2
  677. 2
  678. 2
  679. 2
  680. 2
  681. 2
  682. 2
  683. 2
  684. 2
  685. 2
  686. 2
  687. 2
  688. 2
  689. 2
  690. 2
  691. 2
  692. 2
  693. 2
  694. 2
  695. 2
  696. 2
  697. 2
  698. 2
  699. 2
  700. 2
  701. 2
  702. 2
  703. 2
  704. 2
  705. 2
  706. 2
  707. 2
  708. 2
  709. 2
  710. 2
  711. 2
  712. 2
  713. 2
  714. 2
  715. 2
  716. 2
  717. 2
  718. 2
  719. 2
  720. 2
  721. 2
  722. 2
  723. 2
  724. 2
  725. 2
  726. Sounds good, doesn't work. In theory it can work, but the following is what will happen int the real world: You may be enlightened, but your colleague could not care less, and even if he did, he's barely finishing until the end of the sprint, so in the average case to even suggest having unit tests at that point which will delay results will be frowned upon. Even if you over plan to make sure you have time which is unlikely, expecting that your colleague will modularize the code for the unit tests is the second funniest thing I've ever heard. What your colleague will do is mock the soul out of the code, and write the least amount of tests that reach the minimum coverage, that test nothing but the mocks themselves, and will consequently be very fragile, but not to bugs, but rather any code change that's not a comment. Sometimes they'll also be flaky, which is the funniest thing (at least in hind sight) I've actually experienced (yes, a unit test can be flaky if you're good/bad enough) Trust me you don't have enough time to make your colleague do it in significantly more sensible way if you wish to complete your own work. So let's say you go and refactor it like the enlightened person your are. Well there is just one issue, it turns out that less than 10 percent of the code is something that you could theoretically move to a pure function without side effects, as everything wants to poke the system, and it's spread out, so zero pure functions to extract for you, and simulating the "poked system" is questionable, so it turns out that you just made more small tests that test the mocks. I guess at least you'll have to fix smaller things when you change anything to not catch bugs. Let's say that you're actually working on this nonexistent thing that is just full of pure functionality without side effects, it's like the culmination of leetcode as a bunch of logic. It's your time to shine. When you finish, you feel uncle Bob's proud acknowledging hand on your shoulder as he sheds a tear of pure bliss. You did it, created perfection. That night you have the best sleep ever knowing that you basically brought salvation. One month later you're really busy with other stuff, or sick, so your colleague has to implement a feature in this ultimate existence of code. The first thing your colleague notices is that he has no idea what the hell is happening, because you have 3 line functions. The names are descriptive, but his monkey brain can only remember about the last 4 calls, and has no idea what context he was in a minute ago. He check git blame and identifies you as the anti-christ, but does nothing about it other than remembering this for the rest of his life. Finally he finds what he needs, and he puts in what he needs the quickest and dirtiest way you can imagine, and goes with it. It's not that he could not follow the patter, he just got way to annoyed even before he found what he needed to do it. He tries it, it works, he commits. The pipeline fails. The annoyance he felt before but almost faded completely comes back and goes into overdrive. Now he's really frustrated. He check the tests and contemplates fixing them. He even starts and fixes one with an unnecessary mock, but when he reaches the 2nd one out of the 4, he realizes that he'd have to do something that's not necessarily hard, but he considers to be an extra effort for something he already despises. The result is obvious. 1 test is deleted, one is commented out, and one is disabled (not to mention he did not write any for new stuff). Why not the same treatment? He doesn't know either, it just happened somehow, but the pipeline is green now. You're busy / sick, so you don't review it, but the others will stop this madness from happening right? Riiiight? Well, we all know the answer, After some PR comments 2 typos are fixed in the commented-out test code, and an extra todo comment is added to the commented out and the disabled test. The PR is merged. It is now true production code. Ask the question. Was it your colleague who made tings go sideways? Well, yes, but for him you were the one who set him up to failure. It's supposed to be a relatively small tool but there are about 50 files with countless functions, for him to understand it would take more time then to code It from zero with a similar amount of bugs due to the size. Sometimes less is more.
    2
  727. 2
  728. 2
  729. 2
  730. 2
  731. 2
  732. 2
  733. 2
  734. 2
  735. 2
  736. 2
  737. 2
  738. 2
  739. 2
  740. 2
  741. 2
  742. 2
  743. 2
  744. 2
  745. 2
  746. 2
  747. 2
  748. 2
  749. 2
  750. 2
  751. 2
  752. 2
  753. 2
  754. 2
  755. 2
  756. 2
  757. 2
  758. 2
  759. 2
  760. 2
  761. 2
  762. 2
  763. 2
  764. 2
  765. 2
  766. 2
  767. 2
  768. 2
  769. 2
  770. 2
  771. 2
  772. 2
  773. 2
  774. 2
  775. 2
  776. 2
  777. 2
  778. 2
  779. 2
  780. 2
  781. 2
  782. 2
  783. 2
  784. 2
  785. 2
  786. 2
  787. 2
  788. 2
  789. 2
  790. 2
  791. 2
  792. 2
  793. 2
  794. 2
  795. 2
  796. 2
  797. 2
  798. 2
  799. 2
  800. 2
  801. 2
  802. 2
  803. 2
  804. 2
  805. 2
  806. 2
  807. 2
  808. 2
  809. 2
  810. 2
  811. 2
  812. 2
  813. 2
  814. 2
  815. 2
  816. 2
  817. 2
  818. 2
  819. 2
  820. 2
  821. 2
  822. 1
  823. 1
  824. 1
  825. 1
  826. 1
  827. 1
  828. 1
  829. 1
  830. 1
  831. 1
  832. 1
  833. 1
  834. 1
  835. 1
  836. 1
  837. 1
  838. 1
  839. 1
  840. 1
  841. 1
  842. 1
  843. 1
  844. 1
  845. 1
  846. 1
  847. 1
  848. 1
  849. 1
  850. 1
  851. 1
  852. 1
  853. 1
  854. 1
  855. 1
  856. 1
  857. 1
  858. 1
  859. 1
  860. 1
  861. 1
  862. 1
  863. 1
  864. 1
  865. 1
  866. 1
  867. 1
  868. 1
  869. 1
  870. 1
  871. 1
  872. 1
  873. 1
  874. 1
  875. 1
  876. 1
  877. 1
  878. 1
  879. 1
  880. 1
  881. 1
  882. 1
  883. 1
  884. 1
  885. 1
  886. 1
  887. 1
  888. 1
  889. 1
  890. 1
  891. 1
  892. 1
  893. 1
  894. 1
  895. 1
  896. 1
  897. 1
  898. 1
  899. 1
  900. 1
  901. 1
  902. 1
  903. 1
  904. 1
  905. 1
  906. 1
  907. 1
  908. 1
  909. 1
  910. 1
  911. 1
  912. 1
  913. 1
  914. 1
  915. 1
  916. 1
  917. 1
  918. 1
  919. 1
  920. 1
  921. 1
  922. 1
  923. 1
  924. 1
  925. 1
  926. 1
  927. 1
  928. 1
  929. 1
  930. 1
  931. 1
  932. 1
  933. 1
  934. 1
  935. 1
  936. 1
  937. 1
  938. 1
  939. 1
  940. 1
  941. 1
  942. 1
  943. 1
  944. 1
  945. 1
  946. 1
  947. 1
  948. 1
  949. 1
  950. 1
  951. 1
  952. 1
  953. 1
  954. 1
  955. 1
  956. 1
  957. 1
  958. 1
  959. 1
  960. 1
  961. 1
  962. 1
  963. 1
  964. 1
  965. 1
  966. 1
  967. 1
  968. 1
  969. 1
  970. 1
  971. 1
  972. 1
  973. 1
  974. 1
  975. 1
  976. 1
  977. 1
  978. 1
  979. 1
  980. 1
  981. 1
  982. 1
  983. 1
  984. 1
  985. 1
  986. 1
  987. 1
  988. 1
  989. 1
  990. 1
  991. 1
  992. 1
  993. 1
  994. 1
  995. 1
  996. 1
  997. 1
  998. 1
  999. 1
  1000. 1
  1001. 1
  1002. 1
  1003. 1
  1004. 1
  1005. 1
  1006. 1
  1007. 1
  1008. 1
  1009. 1
  1010. 1
  1011. 1
  1012. 1
  1013. 1
  1014. 1
  1015. 1
  1016. 1
  1017. 1
  1018. 1
  1019. 1
  1020. 1
  1021. 1
  1022. 1
  1023. 1
  1024. 1
  1025. 1
  1026. 1
  1027. 1
  1028. 1
  1029. 1
  1030. 1
  1031. 1
  1032. 1
  1033. 1
  1034. 1
  1035. 1
  1036. 1
  1037. 1
  1038. 1
  1039. 1
  1040. 1
  1041. 1
  1042. 1
  1043. 1
  1044. 1
  1045. 1
  1046. 1
  1047. 1
  1048. 1
  1049. 1
  1050. 1
  1051. 1
  1052. 1
  1053. 1
  1054. 1
  1055. 1
  1056. 1
  1057. 1
  1058. 1
  1059. 1
  1060. 1
  1061. 1
  1062. 1
  1063. 1
  1064. 1
  1065. 1
  1066. 1
  1067. 1
  1068. 1
  1069. 1
  1070. 1
  1071. 1
  1072. 1
  1073. 1
  1074. 1
  1075. 1
  1076. 1
  1077. 1
  1078. 1
  1079. 1
  1080. 1
  1081. 1
  1082. 1
  1083. 1
  1084. 1
  1085. 1
  1086. 1
  1087. 1
  1088. 1
  1089. 1
  1090. 1
  1091. 1
  1092. 1
  1093. 1
  1094. 1
  1095. 1
  1096. 1
  1097. 1
  1098. 1
  1099. 1
  1100. 1
  1101. 1
  1102. 1
  1103. 1
  1104. 1
  1105. 1
  1106. 1
  1107. 1
  1108. 1
  1109. 1
  1110. 1
  1111. 1
  1112. 1
  1113. 1
  1114. 1
  1115. 1
  1116. 1
  1117. 1
  1118. 1
  1119. 1
  1120. 1
  1121. 1
  1122. 1
  1123. 1
  1124. 1
  1125. 1
  1126. 1
  1127. 1
  1128. 1
  1129. 1
  1130. 1
  1131. 1
  1132. 1
  1133. 1
  1134. 1
  1135. 1
  1136. 1
  1137. 1
  1138. 1
  1139. 1
  1140. 1
  1141. 1
  1142. 1
  1143. 1
  1144. 1
  1145. 1
  1146. 1
  1147. 1
  1148. 1
  1149. 1
  1150. 1
  1151. 1
  1152. 1
  1153. 1
  1154. 1
  1155. 1
  1156. 1
  1157. 1
  1158. 1
  1159. 1
  1160. 1
  1161. 1
  1162. 1
  1163. 1
  1164. 1
  1165. 1
  1166. 1
  1167. 1
  1168. 1
  1169. 1
  1170. 1
  1171. 1
  1172. 1
  1173. 1
  1174. 1
  1175. 1
  1176. 1
  1177. 1
  1178. 1
  1179. 1
  1180. 1
  1181. 1
  1182. 1
  1183. 1
  1184. 1
  1185. 1
  1186. 1
  1187. 1
  1188. 1
  1189. 1
  1190. 1
  1191. 1
  1192. 1
  1193. 1
  1194. 1
  1195. 1
  1196. 1
  1197. 1
  1198. 1
  1199. 1
  1200. 1
  1201. 1
  1202. 1
  1203. 1
  1204. 1
  1205. 1
  1206. 1
  1207. 1
  1208. 1
  1209. 1
  1210. 1
  1211. 1
  1212. 1
  1213. 1
  1214. 1
  1215. 1
  1216. 1
  1217. 1
  1218. 1
  1219. 1
  1220. 1
  1221. 1
  1222. 1
  1223. 1
  1224. 1
  1225. 1
  1226. 1
  1227. 1
  1228. 1
  1229. 1
  1230. 1
  1231. 1
  1232. 1
  1233. 1
  1234. 1
  1235. 1
  1236. 1
  1237. 1
  1238. 1
  1239. 1
  1240. 1
  1241. 1
  1242. 1
  1243. 1
  1244. 1
  1245. 1
  1246. 1
  1247. 1
  1248. 1
  1249. 1
  1250. 1
  1251. 1
  1252. 1
  1253. 1
  1254. 1
  1255. 1
  1256. 1
  1257. 1
  1258. 1
  1259. 1
  1260. 1
  1261. 1
  1262. 1
  1263. 1
  1264. 1
  1265. 1
  1266. 1
  1267. 1
  1268. 1
  1269. 1
  1270. 1
  1271. 1
  1272. 1
  1273. 1
  1274. 1
  1275. 1
  1276. 1
  1277. 1
  1278. 1
  1279. 1
  1280. 1
  1281. 1
  1282. 1
  1283. 1
  1284. 1
  1285. 1
  1286. 1
  1287. 1
  1288. 1
  1289. 1
  1290. 1
  1291. 1
  1292. 1
  1293. 1
  1294. 1
  1295. 1
  1296. 1
  1297. 1
  1298. 1
  1299. 1
  1300. 1
  1301. 1
  1302. 1
  1303. 1
  1304. 1
  1305. 1
  1306. 1
  1307. 1
  1308. 1
  1309. 1
  1310. 1
  1311. 1
  1312. 1
  1313. 1
  1314. 1
  1315. 1
  1316. 1
  1317. 1
  1318. 1
  1319. 1
  1320. 1
  1321. 1
  1322. 1
  1323. 1
  1324. 1
  1325. 1
  1326. 1
  1327. 1
  1328. 1
  1329. 1
  1330. 1
  1331. 1
  1332. 1
  1333. 1
  1334. 1
  1335. 1
  1336. 1
  1337. 1
  1338. 1
  1339. 1
  1340. 1
  1341. 1
  1342. 1
  1343. 1
  1344. 1
  1345. 1
  1346. 1
  1347. 1
  1348. 1
  1349. 1
  1350. 1
  1351. 1
  1352. 1
  1353. 1
  1354. 1
  1355. 1
  1356. 1
  1357. 1
  1358. 1
  1359. 1
  1360. 1
  1361. 1
  1362. 1
  1363. 1
  1364. 1
  1365. 1
  1366. 1
  1367. 1
  1368. 1
  1369. 1
  1370. 1
  1371. 1
  1372. 1
  1373. 1
  1374. 1
  1375. 1
  1376. 1
  1377. 1
  1378. 1
  1379. 1
  1380. 1
  1381. 1
  1382. 1
  1383. 1
  1384. 1
  1385. 1
  1386. 1
  1387. 1
  1388. 1
  1389. 1
  1390. 1
  1391. 1
  1392. 1
  1393. 1
  1394. 1
  1395. 1
  1396. 1
  1397. 1
  1398. 1
  1399. 1
  1400. 1
  1401. 1
  1402. 1
  1403. 1
  1404. 1
  1405. 1
  1406. 1
  1407. 1
  1408. 1
  1409. 1
  1410. 1
  1411. 1
  1412. 1
  1413. 1
  1414. 1
  1415. 1
  1416. 1
  1417. 1
  1418. 1
  1419. 1
  1420. 1
  1421. 1
  1422. 1
  1423. 1
  1424. 1
  1425. 1
  1426. 1
  1427. 1
  1428. 1
  1429. 1
  1430. 1
  1431. 1
  1432. 1
  1433. 1
  1434. 1
  1435. 1
  1436. 1
  1437. 1
  1438. 1
  1439. 1
  1440. 1
  1441. 1
  1442. 1
  1443. 1
  1444. 1
  1445. 1
  1446. 1
  1447. 1
  1448. 1
  1449. 1
  1450. 1
  1451. 1
  1452. 1
  1453. 1
  1454. 1
  1455. 1
  1456. 1
  1457. 1
  1458. 1
  1459. 1
  1460. 1
  1461. 1
  1462. 1
  1463. 1
  1464. 1
  1465. 1
  1466. 1
  1467. 1
  1468. 1
  1469. 1
  1470. 1
  1471. 1
  1472. 1
  1473. 1
  1474. 1
  1475. 1
  1476. 1
  1477. 1
  1478. 1
  1479. 1
  1480. 1
  1481. 1
  1482. 1
  1483. 1
  1484. 1
  1485. 1
  1486. 1
  1487. 1
  1488. 1
  1489. 1
  1490. 1
  1491. 1
  1492. 1
  1493. 1
  1494. 1
  1495. 1
  1496. 1
  1497. 1
  1498. 1
  1499. 1
  1500. 1
  1501. 1
  1502. 1
  1503. 1
  1504. 1
  1505. 1
  1506. 1
  1507. 1
  1508. 1
  1509. 1
  1510. 1
  1511. 1
  1512. 1
  1513. 1
  1514. 1
  1515. 1
  1516. 1
  1517. 1
  1518. 1
  1519. 1
  1520. 1
  1521. 1
  1522. 1
  1523. 1
  1524. 1
  1525. 1
  1526. 1
  1527. 1
  1528. 1
  1529. 1
  1530. 1
  1531. 1
  1532. 1
  1533. 1
  1534. 1
  1535. 1
  1536. 1
  1537. 1
  1538. 1
  1539. 1
  1540. 1
  1541. 1
  1542. 1
  1543. 1
  1544. 1
  1545. 1
  1546. 1
  1547. 1
  1548. 1
  1549. 1
  1550. 1
  1551. 1
  1552. 1
  1553. 1
  1554. 1
  1555. 1
  1556. 1
  1557. 1
  1558. 1
  1559. 1
  1560. 1
  1561. 1
  1562. 1
  1563. 1
  1564. 1
  1565. 1
  1566. 1
  1567. 1
  1568. 1
  1569. 1
  1570. 1
  1571. 1
  1572. 1
  1573. 1
  1574. 1
  1575. 1
  1576. 1
  1577. 1
  1578. 1
  1579. 1
  1580. 1
  1581. 1
  1582. 1
  1583. 1
  1584. 1
  1585. 1
  1586. 1
  1587. 1
  1588. 1
  1589. 1
  1590. 1
  1591. 1
  1592. 1
  1593. 1
  1594. 1
  1595. 1
  1596. 1
  1597. 1
  1598. 1
  1599. 1
  1600. 1
  1601. 1
  1602. 1
  1603. 1
  1604. 1
  1605. 1
  1606. 1
  1607. 1
  1608. 1
  1609. 1
  1610. 1
  1611. 1
  1612. 1
  1613. 1
  1614. 1
  1615. 1
  1616. 1
  1617. 1
  1618. 1
  1619. 1
  1620. 1
  1621. 1
  1622. 1
  1623. 1
  1624. 1
  1625. 1
  1626. 1
  1627. 1
  1628. 1
  1629. 1
  1630. 1
  1631. 1
  1632. 1
  1633. 1
  1634. 1
  1635. 1
  1636. 1
  1637. 1
  1638. 1
  1639. 1
  1640. 1
  1641. 1
  1642. 1
  1643. 1
  1644. 1
  1645. 1
  1646. 1
  1647. 1
  1648. 1
  1649. 1
  1650. 1
  1651. 1
  1652. 1
  1653. 1
  1654. 1
  1655. 1
  1656. 1
  1657. 1
  1658. 1
  1659. 1
  1660. 1
  1661. 1
  1662. Rule of thumb is, less is more. Focus on delivering functionality in a black box. Dont mix up the variables, classes or objects. Set up clean, basic functions that are hyper focused on delivering base of your program. Make it as barebone and simple as it gets to get up and run your functionality properly (simple means done by the standard, and not fucking ducktaped all over the place). Keep the base locked away from rest of the program, add additional details and tweaks as another objects, if you need to modify the base of your program, setup it through functions, put a proper comment above. It has to be precise comment. Every testing modification should be injected from different enclosed space. For example functions and methods do the job here quite nicely. Dont mix up the code that is already working, since you will destroy your ability do debug. With bigger projects, this will lengthen your time spent on finding bugs from 1 hour, to whole week (trust me on this). Ship every new addition to your code, as build up layers upon the core of your program. Its the most important part, do not interfere there unless it is the only option. This way you can roll back functionality without rewriting the core of your application. Use wrappers to do that. Every new functionality should be a working black box. NEVER expose singular variables, functions, methods, or anything like that. Setup your INPUT and OUTPUT. This way you can work on applications as a team, every single programmer can work on his "brick", without interfering into others work. Use every tip mentioned above, to have perfectly readable, and reliable source code, that can be modified with all functionality, without breaking down, or having any memory leaks. It will always compile, and always keep the bare minimum to boot up, and work. Only then, if your parts of the enclosed code are rock solid, and are not to be swapped, you can get down to optimizing process. It will destroy the readability of your code a little bit, but at that point of development it probably wont change anything.
    1
  1663. 1
  1664. 1
  1665. 1
  1666. 1
  1667. 1
  1668. 1
  1669. 1
  1670. 1
  1671. 1
  1672. 1
  1673. 1
  1674. 1
  1675. 1
  1676. 1
  1677. 1
  1678. 1
  1679. 1
  1680. 1
  1681. 1
  1682. 1
  1683. 1
  1684. 1
  1685. 1
  1686. 1
  1687. 1
  1688. 1
  1689. 1
  1690. 1
  1691. 1
  1692. 1
  1693. 1
  1694. 1
  1695. 1
  1696. 1
  1697. 1
  1698. 1
  1699. 1
  1700. 1
  1701. 1
  1702. 1
  1703. 1
  1704. 1
  1705. 1
  1706. 1
  1707. 1
  1708. 1
  1709. 1
  1710. 1
  1711. 1
  1712. 1
  1713. 1
  1714. 1
  1715. 1
  1716. 1
  1717. 1
  1718. 1
  1719. 1
  1720. 1
  1721. 1
  1722. 1
  1723. 1
  1724. 1
  1725. 1
  1726. 1
  1727. 1
  1728. 1
  1729. 1
  1730. 1
  1731. 1
  1732. 1
  1733. 1
  1734. 1
  1735. 1
  1736. 1
  1737. 1
  1738. 1
  1739. 1
  1740. 1
  1741. 1
  1742. 1
  1743. 1
  1744. 1
  1745. 1
  1746. 1
  1747. 1
  1748. 1
  1749. 1
  1750. 1
  1751. 1
  1752. 1
  1753. 1
  1754. 1
  1755. 1
  1756. 1
  1757. 1
  1758. 1
  1759. 1
  1760. 1
  1761. 1
  1762. 1
  1763. 1
  1764. 1
  1765. 1
  1766. 1
  1767. 1
  1768. 1
  1769. 1
  1770. 1
  1771. 1
  1772. 1
  1773. 1
  1774. 1
  1775. 1
  1776. 1
  1777. 1
  1778. 1
  1779. 1
  1780. 1
  1781. 1
  1782. 1
  1783. 1
  1784. 1
  1785. 1
  1786. 1
  1787. 1
  1788. 1
  1789. 1
  1790. 1
  1791. 1
  1792. 1
  1793. 1
  1794. 1
  1795. 1
  1796. 1
  1797. 1
  1798. 1
  1799. 1
  1800. 1
  1801. 1
  1802. 1
  1803. 1
  1804. 1
  1805. 1
  1806. 1
  1807. 1
  1808. 1
  1809. 1
  1810. 1
  1811. 1
  1812. 1
  1813. 1
  1814. 1
  1815. 1
  1816. 1
  1817. 1
  1818. 1
  1819. 1
  1820. 1
  1821. 1
  1822. 1
  1823. 1
  1824. 1
  1825. 1
  1826. 1
  1827. 1
  1828. 1
  1829. 1
  1830. 1
  1831. 1
  1832. 1
  1833. 1
  1834. 1
  1835. 1
  1836. 1
  1837. 1
  1838. 1
  1839. 1
  1840. 1
  1841. 1
  1842. 1
  1843. 1
  1844. 1
  1845. 1
  1846. 1
  1847. 1
  1848. 1
  1849. 1
  1850. 1
  1851. 1
  1852. 1
  1853. 1
  1854. 1
  1855. 1
  1856. 1
  1857. 1
  1858. 1
  1859. 1
  1860. 1
  1861. 1
  1862. 1
  1863. 1
  1864. 1
  1865. 1
  1866. 1
  1867. 1
  1868. 1
  1869. 1
  1870. 1
  1871. 1
  1872. 1
  1873. 1
  1874. 1
  1875. 1
  1876. 1
  1877. 1
  1878. 1
  1879. 1
  1880. 1
  1881. 1
  1882. 1
  1883. 1
  1884. 1
  1885. 1
  1886. 1
  1887. 1
  1888. 1
  1889. 1
  1890. 1
  1891. 1
  1892. 1
  1893. 1
  1894. 1
  1895. 1
  1896. 1
  1897. 1
  1898. 1
  1899. 1
  1900. 1
  1901. 1
  1902. 1
  1903. 1
  1904. 1
  1905. 1
  1906. 1
  1907. 1
  1908. 1
  1909. 1
  1910. 1
  1911. 1
  1912. 1
  1913. 1
  1914. 1
  1915. 1
  1916. 1
  1917. 1
  1918. 1
  1919. 1
  1920. 1
  1921. 1
  1922. 1
  1923. 1
  1924. 1
  1925. 1
  1926. 1
  1927. 1
  1928. 1
  1929. 1
  1930. 1
  1931. 1
  1932. 1
  1933. 1
  1934. 1
  1935. 1
  1936. 1
  1937. 1
  1938. 1
  1939. 1
  1940. 1
  1941. 1
  1942. 1
  1943. 1
  1944. 1
  1945. 1
  1946. 1
  1947. 1
  1948. 1
  1949. 1
  1950. 1
  1951. 1
  1952. 1
  1953. 1
  1954. 1
  1955. 1
  1956. 1
  1957. 1
  1958. 1
  1959. 1
  1960. 1
  1961. 1
  1962. 1
  1963. 1
  1964. 1
  1965. 1
  1966. 1
  1967. 1
  1968. 1
  1969. 1
  1970. 1
  1971. 1
  1972. 1
  1973. 1
  1974. 1
  1975. 1
  1976. 1
  1977. 1
  1978. 1
  1979. 1
  1980. 1
  1981. 1
  1982. 1
  1983. 1
  1984. 1
  1985. 1
  1986. 1
  1987. 1
  1988. 1
  1989. 1
  1990. 1
  1991. 1
  1992. 1
  1993. 1
  1994. 1
  1995. 1
  1996. 1
  1997. 1
  1998. 1
  1999. 1
  2000. 1
  2001. 1
  2002. 1
  2003. 1
  2004. 1
  2005. 1
  2006. 1
  2007. 1
  2008. 1
  2009. 1
  2010. 1
  2011. 1
  2012. 1
  2013. 1
  2014. 1
  2015. 1
  2016. 1
  2017. 1
  2018. 1
  2019. 1
  2020. 1
  2021. 1
  2022. 1
  2023. 1
  2024. 1
  2025. 1
  2026. 1
  2027. 1
  2028. 1
  2029. 1
  2030. 1
  2031. 1
  2032. 1
  2033. 1
  2034. 1
  2035. 1
  2036. 1
  2037. 1
  2038. 1
  2039. 1
  2040. 1
  2041. 1
  2042. 1
  2043. 1
  2044. 1
  2045. 1
  2046. 1
  2047. 1
  2048. 1
  2049. 1
  2050. 1
  2051. 1
  2052. 1
  2053. 1
  2054. 1
  2055. 1
  2056. 1
  2057. 1
  2058. 1
  2059. 1
  2060. 1
  2061. 1
  2062. 1
  2063. 1
  2064. 1
  2065. 1
  2066. 1
  2067. 1
  2068. 1
  2069. 1
  2070. 1
  2071. 1
  2072. 1
  2073. 1
  2074. 1
  2075. 1
  2076. 1
  2077. 1
  2078. 1
  2079. 1
  2080. 1
  2081. 1
  2082. 1
  2083. 1
  2084. 1
  2085. 1
  2086. 1
  2087. 1
  2088. 1
  2089. 1
  2090. 1
  2091. 1
  2092. 1
  2093. 1
  2094. 1
  2095. 1
  2096. 1
  2097. 1
  2098. 1
  2099. 1
  2100. 1
  2101. 1
  2102. 1
  2103. 1
  2104. 1
  2105. 1
  2106. 1
  2107. 1
  2108. 1
  2109. 1
  2110. 1
  2111. 1
  2112. 1
  2113. 1
  2114. 1
  2115. 1
  2116. 1
  2117. 1
  2118. 1
  2119. 1
  2120. 1
  2121. 1
  2122. 1
  2123. 1
  2124. 1
  2125. 1
  2126. 1
  2127. 1
  2128. 1
  2129. 1
  2130. 1
  2131. 1
  2132. 1
  2133. 1
  2134. 1
  2135. 1
  2136. 1
  2137. 1
  2138. 1
  2139. 1
  2140. 1
  2141. 1
  2142. 1
  2143. 1
  2144. 1
  2145. 1
  2146. 1
  2147. 1
  2148. 1
  2149. 1
  2150. 1
  2151. 1
  2152. 1
  2153. 1
  2154. 1
  2155. 1
  2156. 1
  2157. 1
  2158. 1
  2159. 1
  2160. 1
  2161. 1
  2162. 1
  2163. 1
  2164. 1
  2165. 1
  2166. 1
  2167. 1
  2168. 1
  2169. 1
  2170. 1
  2171. 1
  2172. 1
  2173. 1
  2174. 1
  2175. 1
  2176. 1
  2177. 1
  2178. 1
  2179. 1
  2180. 1
  2181. 1
  2182. 1
  2183. 1
  2184. 1
  2185. 1
  2186. 1
  2187. 1
  2188. 1
  2189. 1
  2190. 1
  2191. 1
  2192. 1
  2193. 1
  2194. 1
  2195. 1
  2196. 1
  2197. 1
  2198. 1
  2199. 1
  2200. 1
  2201. 1
  2202. 1
  2203. 1
  2204. 1
  2205. 1
  2206. 1
  2207. 1
  2208. 1
  2209. 1
  2210. 1
  2211. 1
  2212. 1
  2213. 1
  2214. 1
  2215. 1
  2216. 1
  2217. 1
  2218. 1
  2219. 1
  2220. 1
  2221. 1
  2222. 1
  2223. 1
  2224. 1
  2225. 1
  2226. 1
  2227. 1
  2228. 1
  2229. 1
  2230. 1
  2231. 1
  2232. 1
  2233. 1
  2234. 1
  2235. 1
  2236. 1
  2237. 1
  2238. 1
  2239. 1
  2240. 1
  2241. 1
  2242. 1
  2243. 1
  2244. 1
  2245. 1
  2246. 1
  2247. 1
  2248. 1
  2249. 1
  2250. 1
  2251. 1
  2252. 1
  2253. 1
  2254. 1
  2255. 1
  2256. 1
  2257. 1
  2258. 1
  2259. 1
  2260. 1
  2261. 1
  2262. 1
  2263. 1
  2264. 1
  2265. 1
  2266. 1
  2267. 1
  2268. 1
  2269. 1
  2270. 1
  2271. 1
  2272. 1
  2273. 1
  2274. 1
  2275. 1
  2276. 1
  2277. 1
  2278. 1
  2279. 1
  2280. 1
  2281. 1
  2282. 1
  2283. 1
  2284. 1
  2285. 1
  2286. 1
  2287. 1
  2288. 1
  2289. 1
  2290. 1
  2291. I love functions and I think functional programming should be used more mainstream. That said, in the imperative domain, I find that extracting the predicates can often result in less readable code. If you're not using those predicates in other functions, they clutter the source file and usually they're just an unnecessary indirection (e.g. 'isEven(x)' is not significantly more readable than 'x % 2 == 0'). It can look cleaner when everything is behind a nice function but quite often I'd prefer to have "the guts exposed" and in one place so to speak, especially in the imperative domain. If you really want to name the predicate (e.g. isValid := isAuthenticated && isAuthorized) or if you use it multiple times within the function and want to avoid repetition, I think a lambda function (or even a nested function if your language allows them) is better than defining a new function in the outer scope. If you do this, I don't have any objections about extracting as long as you can actually name the thing sensibly. Which leads me to the other thing I wanted to comment. I don't disagree about naming things meaningfully of course but that's easier said than done. I think often it's just impossible because the things people work with can be highly specific and far removed from everyday reality. I might also have a slightly deviant interpretation of what it means to give things meaningful names, e.g. I think it's perfectly fine to use one letter variables when the variable represents something generic (find e (x:xs) = ...), and ofc the classic i, j, and k for loop variables. Also longer names (classic OOP trope) doesn't mean they're better; consider the "BeanContextServicesSupport.BCSSServiceProvider" class or literally anything else from the Java API. I'm sure whoever named that did their best to name it as clearly as possible (still I wonder what's the point of adding the seemingly redundant "BCSS" there instead of just "ServiceProvider"?) but things like that just can't be named "meaningfully" to anyone who isn't already familiar with "BeanContextServices" and so on. I'll end it here before I start rambling about how terrible OOP is again.
    1
  2292. 1
  2293. 1
  2294. 1
  2295. 1
  2296. 1
  2297. 1
  2298. 1
  2299. 1
  2300. 1
  2301. 1
  2302. 1
  2303. 1
  2304. 1
  2305. 1
  2306. 1
  2307. 1
  2308. 1
  2309. 1
  2310. 1
  2311. 1
  2312. 1
  2313. 1
  2314. 1
  2315. 1
  2316. 1
  2317. 1
  2318. 1
  2319. 1
  2320. 1
  2321. 1
  2322. 1
  2323. 1
  2324. 1
  2325. 1
  2326. 1
  2327. 1
  2328. 1
  2329. 1
  2330. 1
  2331. 1
  2332. 1
  2333. 1
  2334. 1
  2335. 1
  2336. 1
  2337. 1
  2338. 1
  2339. 1
  2340. 1
  2341. 1
  2342. 1
  2343. 1
  2344. 1
  2345. 1
  2346. 1
  2347. 1
  2348. 1
  2349. 1
  2350. 1
  2351. 1
  2352. 1
  2353. 1
  2354. 1
  2355. 1
  2356. 1
  2357. 1
  2358. 1
  2359. 1
  2360. 1
  2361. 1
  2362. 1
  2363. 1
  2364. 1
  2365. 1
  2366. 1
  2367. 1
  2368. 1
  2369. 1
  2370. 1
  2371. 1
  2372. 1
  2373. 1
  2374. 1
  2375. 1
  2376. 1
  2377. 1
  2378. 1
  2379. 1
  2380. 1
  2381. 1
  2382. 1
  2383. 1
  2384. 1
  2385. 1
  2386. 1
  2387. 1
  2388. 1
  2389. 1
  2390. 1
  2391. 1
  2392. 1
  2393. 1
  2394. 1
  2395. 1
  2396. 1
  2397. 1
  2398. 1
  2399. 1
  2400. 1
  2401. 1
  2402. 1
  2403. 1
  2404. 1
  2405. 1
  2406. 1
  2407. 1
  2408. 1
  2409. 1
  2410. 1
  2411. 1
  2412. 1
  2413. 1
  2414. 1
  2415. 1
  2416. 1
  2417. 1
  2418. Someþing pretty funny I realized is ðat in C programming ðe use of "goto" is accepted for error handling. You see, when you call functions that might fail, you read its return value and if it fails you, obviously, handle ðe error. However, in ðat error handling you might have to do some cleanup and closing, and you might end up repeating a lot of code when writing your error handlers. // for example int get_some_strings(){ size_t len = 0; char* str1 = NULL; if(getline(&str1, &len, stdin) < 0){ return 1; //ok } char* str2 = NULL; if(getline(&str2, &len, stdin) < 0){ free(str1); return 1; // still ok } char* str3 = NULL; if(getline(&str3, &len, stdin) < 0){ free(str1); free(str2); return 1; //well } char* str4 = NULL; if(getline(&str4, &len, stdin) < 0){ free(str1); free(str2); free(str3); return 1; // oof } free(str4); free(str3); free(str2); free(str1); return 0; } // See how ðe cleanups stack up? To solve ðis problem, ðere are two techniques, one is just creating a function for cleanup like ðis. void cleanup(char* s1, char* s2, char* s3, char* s4){ if(s1 != NULL) free(s1); if(s2 != NULL) free(s2); if(s3 != NULL) free(s3); if(s4 != NULL) free(s4); } int get_some_strings(){ size_t len = 0; char* str1 = NULL; if(getline(&str1, &len, stdin) < 0){ return 1; } char* str2 = NULL; if(getline(&str2, &len, stdin) < 0){ cleanup(str1, NULL, NULL, NULL); return 1; } char* str3 = NULL; if(getline(&str3, &len, stdin) < 0){ cleanup(str1, str2, NULL, NULL); return 1; } char* str4 = NULL; if(getline(&str4, &len, stdin) < 0){ cleanup(str1, str2, str3, NULL); return 1; } cleanup(str1, str2, str3, str4); return 0; } // much better And ðe oðer is using gotos to jump to ðe cleanup section int get_some_strings(){ int rv = 0; size_t len = 0; char* str1 = NULL; if(getline(&str1, &len, stdin) < 0){ return 1; } char* str2 = NULL; if(getline(&str2, &len, stdin) < 0){ rv = 1; goto cleanup1; } char* str3 = NULL; if(getline(&str3, &len, stdin) < 0){ rv = 1; goto cleanup2; } char* str4 = NULL; if(getline(&str4, &len, stdin) < 0){ rv = 1; goto cleanup3; } free(str4); cleanup3: free(str3); cleanup2: free(str2); cleanup1: free(str1); return rv; } // also better Each way of avoiding repetition in your code have some advantages over ðe oðer (using a cleanup function tends to look more elegant and makes your main function less cluttered, while using gotos avoids function call overhead and is easier to refactor).
    1
  2419. 1
  2420. 1