PageSourceSearch

https://blog.byndyu.ru/2008/12/blog-post.html

html byndyu.ru collected 2026-09-24 08:59:24 UTC 128,501 bytes, 2,549 lines download raw bytes

1<!DOCTYPE html>
2<html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
3<head>
4<link href='https://www.blogger.com/static/v1/widgets/2872013778-css_bundle_v2.css' rel='stylesheet' type='text/css'/>
5<meta content='IE=EmulateIE7' http-equiv='X-UA-Compatible'/>
6<meta content='h9ge3UBxect-8ANCzzfrCPKuna5jRG6KoycugGp5ebY' name='google-site-verification'/>
7<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet'/>
8<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro' rel='stylesheet'/>
9<!--b:if cond='data:blog.isMobile'> <b:else/-->
10<meta content='width=device-width, initial-scale=1' name='viewport'/>
11<!--/b:if-->
12<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
13<meta content='blogger' name='generator'/>
14<link href='https://blog.byndyu.ru/favicon.ico' rel='icon' type='image/x-icon'/>
15<link href='https://blog.byndyu.ru/2008/12/blog-post.html' rel='canonical'/>
16<link rel="alternate" type="application/atom+xml" title="Блог Александра Бындю - Atom" href="https://blog.byndyu.ru/feeds/posts/default" />
17<link rel="alternate" type="application/rss+xml" title="Блог Александра Бындю - RSS" href="https://blog.byndyu.ru/feeds/posts/default?alt=rss" />
18<link rel="service.post" type="application/atom+xml" title="Блог Александра Бындю - Atom" href="https://www.blogger.com/feeds/458002489272917533/posts/default" />
19
20<link rel="alternate" type="application/atom+xml" title="Блог Александра Бындю - Atom" href="https://blog.byndyu.ru/feeds/2002061643571794461/comments/default" />
21<!--Can't find substitution for tag [blog.ieCssRetrofitLinks]-->
22<link href='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s1600/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg' rel='image_src'/>
23<meta content='https://blog.byndyu.ru/2008/12/blog-post.html' property='og:url'/>
24<meta content='Технические долги' property='og:title'/>
25<meta content='Этот термин впервые ввел Ward Cunningham :    Технические долги включают ту работу в проекте, которую мы решаем (хорошо, если осознанно) не ...' property='og:description'/>
26<meta content='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/w1200-h630-p-k-no-nu/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg' property='og:image'/>
27<title>Блог Александра Бындю: Технические долги</title>
28<style id='page-skin-1' type='text/css'><!--
29/*-----------------------------------------------
30Blogger Template Style
31Name:     Picture Window
32Designer: Josh Peterson
33URL:      www.noaesthetic.com
34----------------------------------------------- */
35/* Variable definitions
36====================
37<Variable name="keycolor" description="Main Color" type="color" default="#1a222a"/>
38<Variable name="body.background" description="Body Background" type="background"
39color="#ffffff" default="#111111 url(https://themes.googleusercontent.com/image?id=1OACCYOE0-eoTRTfsBuX1NMN9nz599ufI1Jh0CggPFA_sK80AGkIr8pLtYRpNUKPmwtEa) repeat-x fixed top center"/>
40<Group description="Page Text" selector=".content-inner">
41<Variable name="body.font" description="Font" type="font"
42default="normal normal 16px 'Source Sans Pro', sans-serif"/>
43<Variable name="body.text.color" description="Text Color" type="color" default="#333333"/>
44</Group>
45<Group description="Backgrounds" selector=".body-fauxcolumns-outer">
46<Variable name="body.background.color" description="Outer Background" type="color" default="#296695"/>
47<Variable name="header.background.color" description="Header Backgroun
47d" type="color" default="transparent"/>
48<Variable name="post.background.color" description="Post Background" type="color" default="#ffffff"/>
49</Group>
50<Group description="Links" selector=".main-outer">
51<Variable name="link.color" description="Link Color" type="color" default="#336699"/>
52<Variable name="link.visited.color" description="Visited Color" type="color" default="#6699cc"/>
53<Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/>
54</Group>
55<Group description="Blog Title" selector=".header">
56<Variable name="header.font" description="Title Font" type="font"
57default="normal normal 36px 'Source Sans Pro', sans-serif"/>
58<Variable name="header.text.color" description="Text Color" type="color" default="#111111" />
59</Group>
60<Group description="Tabs Text" selector=".tabs-outer .PageList">
61<Variable name="tabs.font" description="Font" type="font"
62default="normal normal 15px 'Source Sans Pro', sans-serif"/>
63<Variable name="tabs.text.color" description="Text Color" type="color" default="#ffffff"/>
64<Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#992211"/>
65</Group>
66<Group description="Tabs Background" selector=".tabs-outer .PageList">
67<Variable name="tabs.background.color" description="Background Color" type="color" default="transparent"/>
68<Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="transparent"/>
69<Variable name="tabs.separator.color" description="Separator Color" type="color" default="transparent"/>
70</Group>
71<Group description="Post" selector=".post">
72<Variable name="post.title.font" description="Title Font" type="font"
73default="normal normal 18px 'Source Sans Pro', sans-serif"/>
74<Variable name="post.footer.text.color" description="Footer Text Color" type="color" default="#999999"/>
75<Variable name="post.border.color" description="Border Color" type="color" default="#dddddd"/>
76</Group>
77<Group description="Gadgets" selector=".sidebar .widget">
78<Variable name="widget.title.font" description="Title Font" type="font"
79default="bold normal 13px 'Source Sans Pro', sans-serif"/>
80<Variable name="widget.title.text.color" description="Title Color" type="color" default="#888888"/>
81</Group>
82<Group description="Footer" selector=".footer-outer">
83<Variable name="footer.text.color" description="Text Color" type="color" default="#cccccc"/>
84<Variable name="footer.widget.title.text.color" description="Gadget Title Color" type="color" default="#aaaaaa"/>
85</Group>
86<Group description="Footer Links" selector=".footer-outer">
87<Variable name="footer.link.color" description="Link Color" type="color" default="#99ccee"/>
88<Variable name="footer.link.visited.color" description="Visited Color" type="color" default="#77aaee"/>
89<Variable name="footer.link.hover.color" description="Hover Color" type="color" default="#33aaff"/>
90</Group>
91<Variable name="content.margin" description="Content Margin Top" type="length" default="20px"/>
92<Variable name="content.padding" description="Content Padding" type="length" default="0"/>
93<Variable name="content.background" description="Content Backgroun
93d" type="background"
94default="transparent none repeat scroll top left"/>
95<Variable name="content.border.radius" description="Content Border Radius" type="length" default="0"/>
96<Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="0"/>
97<Variable name="header.padding" description="Header Padding" type="length" default="0"/>
98<Variable name="header.background.gradient" description="Header Gradient" type="url"
99default="none"/>
100<Variable name="header.border.radius" description="Header Border Radius" type="length" default="0"/>
101<Variable name="main.border.radius.top" description="Main Border Radius" type="length" default="20px"/>
102<Variable name="footer.border.radius.top" description="Footer Border Radius Top" type="length" default="0"/>
103<Variable name="footer.border.radius.bottom" description="Footer Border Radius Bottom" type="length" default="20px"/>
104<Variable name="region.shadow.spread" description="Main and Footer Shadow Spread" type="length" default="3px"/>
105<Variable name="region.shadow.offset" description="Main and Footer Shadow Offset" type="length" default="1px"/>
106<Variable name="tabs.background.gradient" description="Tab Background Gradient" type="url" default="none"/>
107<Variable name="tab.selected.background.gradient" description="Selected Tab Background" type="url"
108default="url(https://www.blogblog.com/1kt/transparent/white80.png)"/>
109<Variable name="tab.background" description="Tab Background" type="background"
110default="transparent url(https://www.blogblog.com/1kt/transparent/black50.png) repeat scroll top left"/>
111<Variable name="tab.border.radius" description="Tab Border Radius" type="length" default="0px" />
112<Variable name="tab.first.border.radius" description="First Tab Border Radius" type="length" default="0px" />
113<Variable name="tabs.border.radius" description="Tabs Border Radius" type="length" default="0px" />
114<Variable name="tabs.spacing" description="Tab Spacing" type="length" default=".25em"/>
115<Variable name="tabs.margin.bottom" description="Tab Margin Bottom" type="length" default="0"/>
116<Variable name="tabs.margin.sides" description="Tab Margin Sides" type="length" default="20px"/>
117<Variable name="main.background" description="Main Background" type="background"
118default="transparent url(https://www.blogblog.com/1kt/transparent/white80.png) repeat scroll top left"/>
119<Variable name="main.padding.sides" description="Main Padding Sides" type="length" default="20px"/>
120<Variable name="footer.background" description="Footer Background" type="background"
121default="transparent url(https://www.blogblog.com/1kt/transparent/black50.png) repeat scroll top left"/>
122<Variable name="post.margin.sides" description="Post Margin Sides" type="length" default="-20px"/>
123<Variable name="post.border.radius" description="Post Border Radius" type="length" default="5px"/>
124<Variable name="widget.title.text.transform" description="Widget Title Text Transform" type="string" default="uppercase"/>
125<Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/>
126<Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/>
127*/
128
129--></style>
130<style id='template-skin-1' type='text/css'><!--
131/* Content
132----------------------------------------------- */
133:root {
134--blog-accent: #b83d25;
135--blog-accent-dark: #92301f;
136--blog-text: #181817;
137--blog-muted: #73716d;
138--blog-line: #e5e1da;
139--blog-sidebar: #f1efeb;
140--blog-quote: #f7f3ef;
141--blog-radius: 12px;
142}
143html,
144body {
145font-family: "Source Sans Pro", sans-serif !important;
146}
147body {
148overflow-x: hidden;
149color: var(--blog-text);
150background: #fff;
151font-size: 18px;
152text-rendering: optimizeLegibility;
153-webkit-font-smoothing: antialiased;
154}
155.sidebar {
156overflow-x: hidden;
157overflow-y: auto;
158}
159html body .region-inner {
160width: auto;
161min-width: 0;
162max-width: 100%;
163}
164body .navbar {
165position: fixed;
166top: 0;
167z-index: 1000;
168width: 100%;
169background: #ddd;
170}
171body .content {
172margin-top: 30px;
173}
174.content-outer {
175margin: 0 auto;
176background: transparent url(https://www.blogblog.com/1kt/transparent/white80.png) repeat scroll top left;
177border-radius: 15px;
178box-shadow: none;
179}
180.content-inner {
181margin: 0 auto;
182padding: 0 60px;
183}
184a:link,
185a:visited {
186color: #000;
187text-decoration: none;
188}
189a:hover {
190color: var(--blog-accent);
191text-decoration: none;
192border-bottom: 0;
193}
194a:focus-visible,
195button:focus-visible {
196outline: 3px solid rgba(184, 61, 37, 0.4);
197outline-offset: 4px;
198border-radius: 4px;
199}
200.p {
201text-indent: 1.2em;
202}
203.reaction-buttons {
204font-size: 14px;
205}
206.reaction-buttons a {
207color: #999696 !important;
208}
209.is-hidden {
210display: none !important;
211}
212/* Header
213----------------------------------------------- */
214.header-outer {
215display: none;
216}
217.Header img,
218.Header #header-inner {
219border-radius: 10px;
220}
221.header-inner .Header .titlewrapper,
222.header-inner .Header .descriptionwrapper {
223padding-right: 30px;
224padding-left: 30px;
225}
226.Header h1 {
227font: 36px "Source Sans Pro", sans-serif;
228}
229.Header .description {
230color: #666464;
231font-size: 130%;
232}
233#header {
234border-bottom: 1px solid #ccc;
235}
236.header.section {
237height: 180px !important;
238border: 0 !important;
239}
240.descriptionwrapper {
241padding-bottom: 5px;
242}
243.titlewrapper .title,
244.descriptionwrapper .description {
245display: inline;
246}
247.titlewrapper .title {
248font-size: 28px;
249}
250.titlewrapper .title a {
251text-decoration: none;
252border: 0;
253}
254.descriptionwrapper .description {
255padding-bottom: 18px;
256font-size: 16px;
257line-height: 1.04;
258}
259/* Navigation
260----------------------------------------------- */
261.tabs-inner {
262margin: 0.5em 0 0;
263padding: 0;
264}
265.tabs-inner .section {
266margin: 0;
267padding-left: 330px;
268}
269.tabs-inner .widget ul {
270padding: 0;
271border-radius: 0;
272}
273.tabs-inner .widget li {
274border: 0;
275}
276.tabs-inner .widget li a {
277display: inline-block;
278margin-right: 15px;
279color: #000;
280font-size: 16px;
281border-right: 1px solid transparent;
282border-radius: 0;
283}
284.PageList li.selected a,
285.PopularPosts li.selected a {
286font-weight: 400;
287}
288.tabs-inner .widget li.selected a,
289.tabs-inner .widget li a:hover {
290position: relative;
291z-index: 1;
292color: var(--blog-accent);
293background: transparent url(https://www.blogblog.com/1kt/transparent/tabs_gradient_shade.png) repeat-x bottom;
294}
295.tabs-inner .widget li.selected a {
296padding-bottom: 2px;
297border-right: 0;
298border-bottom: 2px solid var(--blog-accent);
299}
300#PageList2 .widget-content {
301max-width: 800px;
302margin: 20px auto 0 !important;
303}
304#PageList2 .widget-content ul {
305display: flex;
306flex-wrap: wrap;
307align-items: center;
308gap: 8px 24px;
309padding: 0 !important;
310}
311#PageList2 .widget-content li {
312width: auto !important;
313margin: 0 !important;
314}
315#PageList2 .widget-content a {
316display: inline-block;
317padding: 6px 0;
318color: var(--blog-muted);
319line-height: 1.35;
320transition: color 150ms;
321}
322#PageList2 .widget-content a:hover {
323color: var(--blog-accent);
324}
325#PageList2 .widget-content li.selected a {
326color: var(--blog-accent);
327background: none;
328border-bottom: 2px solid var(--blog-accent);
329}
330/* Blogger column layout
331----------------------------------------------- */
332.content-outer,
333.content-fauxcolumn-outer,
334.region-inner {
335min-width: 80%;
336}
337.dsq-comment {
338min-width: 250px;
339}
340.main-inner .columns {
341padding-right: 0;
342padding-left: 330px;
343}
344.main-inner .fauxcolumn-center-outer {
345right: 0;
346left: 330px;
347}
348.main-inner .fauxcolumn-left-outer {
349width: 330px;
350}
351.main-inner .fauxcolumn-right-outer,
352.main-inner .column-right-outer {
353width: 0;
354}
355.main-inner .column-left-outer {
356right: 100%;
357width: 330px;
358margin-left: -330px;
359}
360.main-inner .column-right-outer {
361margin-right: 0;
362}
363#layout {
364min-width: 0;
365}
366#layout .content-outer {
367width: 800px;
368min-width: 0;
369}
370#layout .region-inner {
371width: auto;
372min-width: 0;
373}
374#b-navbar {
375background: #ddd;
376}
377/* Main content
378----------------------------------------------- */
379.main-outer {
380background: none;
381border-radius: 0;
382box-shadow: none;
383}
384.main-inner {
385margin-top: 28px !important;
386padding: 15px 5px 20px;
387}
388.main-inner .column-center-inner {
389padding: 0;
390}
391.main-inner .column-left-inner {
392padding-left: 0;
393}
394.main-inner .column-right-inner {
395padding-right: 0;
396padding-left: 60px;
397}
398.blog-posts {
399max-width: 800px;
400margin: 28px auto 0 !important;
401}
402.blog-posts--header {
403font-size: 30px !important;
404line-height: 1.3 !important;
405}
406h2 {
407margin: 0.5em 0;
408color: #666;
409text-transform: uppercase;
410}
411/* Posts
412----------------------------------------------- */
413.post-outer {
414margin: 0 -20px 64px;
415padding: 0 140px 64px 40px;
416background: #fff;
417border-bottom: 1px solid var(--blog-line);
418border-radius: 4px !important;
419}
420.post-body {
421position: relative;
422font-size: 19px;
423line-height: 1.65;
424}
425h1.post-title,
426h3.post-title {
427margin: 10px 0 0;
428padding-bottom: 20px;
429color: #000;
430font-size: 38px;
431font-weight: 600;
432line-height: 1.12;
433letter-spacing: -0.015em;
434}
435h1.post-title a,
436h3.post-title a {
437color: var(--blog-accent) !important;
438}
439h1.post-title a:hover,
440h3.post-title a:hover {
441color: var(--blog-accent-dark) !important;
442text-decoration: none;
443border-bottom: 0;
444}
445.post-header {
446margin: -15px 0 25px;
447color: #999;
448line-height: 1.6;
449}
450.post-outer h2.date-header {
451margin-bottom: 24px;
452color: var(--blog-muted);
453font-size: 13px;
454font-weight: 400;
455line-height: 1.14;
456letter-spacing: 0.07em;
457text-align: left;
458text-transform: uppercase;
459}
460.post-body p {
461margin: 0 0 1.3em;
462color: #000;
463text-align: left;
464}
465.post-body h2 {
466margin: 2.2em 0 0.7em !important;
467font-size: 29px;
468line-height: 1.25;
469letter-spacing: -0.01em;
470}
471.post-body h3 {
472margin: 1.8em 0 0.6em !important;
473font-size: 23px;
474font-weight: 400 !important;
475line-height: 1.3;
476}
477.post-body h4,
478.post-body h5,
479.post-body h6 {
480margin-top: 5px;
481margin-bottom: 20px;
482}
483.post-inner-title {
484padding-top: 0 !important;
485}
486h2.post-inner-title {
487color: #000;
488}
489h3.post-inner-title {
490color: #000;
491}
492h4.post-inner-title {
493color: #000;
494}
495.entry-title__list {
496line-height: 0.9 !important;
497}
498.post-body a {
499color: var(--blog-accent) !important;
500text-decoration: underline;
501text-decoration-thickness: 1px;
502text-underline-offset: 3px;
503border-bottom: 0 !important;
504}
505.post-body a:hover {
506color: var(--blog-accent-dark) !important;
507}
508.post-body .separator a {
509margin-left: 0 !important;
510text-decoration: none;
511}
512blockquote {
513margin-top: 10px;
514margin-bottom: 25px;
515margin-left: 0;
516padding: 15px 20px 35px;
517color: #000;
518background: #f3f5f6;
519border-left: 0;
520font-size: 18px;
521line-height: 1.56;
522text-align: left;
523}
524.post-body blockquote {
525box-sizing: border-box;
526margin: 32px 0 !important;
527padding: 20px 24px !important;
528background: var(--blog-quote);
529border-left: 4px solid var(--blog-accent) !important;
530border-radius: 0 var(--blog-radius) var(--blog-radius) 0;
531font-size: 18px;
532line-height: 1.6;
533}
534.separator img {
535max-width: 100%;
536}
537.post-body img {
538display: block;
539box-sizing: border-box;
540max-width: 100%;
541height: auto;
542border: 1px solid var(--blog-line);
543border-radius: var(--blog-radius);
544}
545.post-body a img {
546cursor: zoom-in;
547}
548.image-left {
549float: left;
550margin: 0 1rem 1rem 0;
551}
552.image-right {
553float: right;
554margin: 0 0 1rem 1rem;
555}
556.entry-content iframe {
557max-width: 100%;
558}
559.post-body pre {
560max-width: 100%;
561padding: 18px 20px;
562overflow-x: auto;
563color: #f5f5f5;
564background: #202124;
565border-radius: var(--blog-radius);
566line-height: 1.55;
567}
568.post-body code:not(pre code) {
569padding: 0.15em 0.35em;
570background: #f1efeb;
571border-radius: 4px;
572}
573.post-body table {
574display: block;
575max-width: 100%;
576overflow-x: auto;
577border-collapse: collapse;
578}
579.post-body th,
580.post-body td {
581padding: 10px 12px;
582border: 1px solid var(--blog-line);
583}
584.post-outer-ads {
585margin: 0 -20px 20px;
586padding: 0 20px;
587color: #333;
588background: #fff;
589border: 0 !important;
590border-radius: 10px;
591font-size: 110%;
592}
593.post-outer-ads .post-title {
594margin: 0;
595}
596.clearfix::before,
597.clearfix::after {
598display: table;
599content: "";
600}
601.clearfix::after {
602clear: both;
603}
604/* Post footer and pagination
605----------------------------------------------- */
606.post-footer {
607margin-top: 20px;
608font-size: 16px;
609line-height: 1.25;
610letter-spacing: 0;
611}
612.post-footer abbr {
613color: #000;
614text-decoration: none;
615}
616.post-footer-line {
617margin-bottom: 20px;
618}
619.jump-link {
620display: block !important;
621margin-top: 24px;
622}
623.jump-link a {
624display: inline-flex;
625align-items: center;
626min-height: 42px;
627padding: 9px 15px;
628color: var(--blog-accent) !important;
629background: #fff;
630border: 1px solid var(--blog-accent) !important;
631border-radius: 9px;
632font-size: 16px;
633font-weight: 600;
634line-height: 1.25;
635}
636.jump-link a:hover {
637color: #fff !important;
638background: var(--blog-accent);
639}
640.post-backlinks.post-comment-link a,
641.disqus-blogger-comment-link {
642color: #999696 !important;
643font-size: 14px;
644line-height: 1.25;
645text-align: left;
646}
647#blog-pager {
648display: flex;
649flex-wrap: wrap;
650gap: 12px;
651margin-top: 48px;
652padding-top: 24px;
653border-top: 1px solid var(--blog-line);
654text-align: left;
655}
656#blog-pager a {
657display: inline-flex;
658margin: 0 !important;
659padding: 9px 14px;
660color: #999696;
661border: 1px solid var(--blog-line);
662border-radius: 9px;
663font-size: 16px;
664}
665#blog-pager .home-link,
666#blog-pager #blog-pager-older-link,
667#blog-pager #blog-pager-newer-link {
668float: none;
669}
670/* Comments
671----------------------------------------------- */
672#comments {
673margin-top: 70px !important;
674}
675.comments h4 {
676margin: 1em 0 0;
677font: 18px "Source Sans Pro", sans-serif;
678}
679#comments .comment-author {
680padding-top: 1.5em;
681background-position: 0 1.5em;
682border-top: 1px dashed rgba(128, 128, 128, 0.5);
683}
684#comments .comment-author:first-child {
685padding-top: 0;
686border-top: 0;
687}
688.avatar-image-container {
689margin: 0.2em 0 0;
690}
691/* Widgets
692----------------------------------------------- */
693.widget ul,
694.widget #ArchiveList ul.flat {
695padding-left: 40px;
696list-style: disc;
697}
698.widget ul li,
699.widget #ArchiveList ul.flat li {
700border-top: 0;
701}
702.widget .post-body > ul,
703.widget .post-body > ol {
704margin-top: -20px;
705}
706.widget .post-body ul {
707margin-bottom: 20px;
708list-style: none;
709}
710.widget .post-body .separator ~ ul,
711.widget .post-body .separator ~ ol {
712margin-top: 20px;
713}
714.widget .post-body ul > li::before {
715margin-left: -30px;
716content: "\2014\00a0";
717}
718.widget .post-body li {
719margin-bottom: 13px !important;
720border: 0;
721}
722.PopularPosts .widget-content ul li {
723padding: 0.25em 0;
724}
725/* Footer
726----------------------------------------------- */
727.footer-outer {
728color: #921;
729background: none;
730border-radius: 10px;
731box-shadow: none;
732}
733.footer-inner {
734padding: 0 5px 20px;
735}
736.footer-outer a {
737color: #ffffdd;
738}
739.footer-outer a:visited {
740color: #cccc99;
741}
742.footer-outer a:hover {
743color: var(--blog-accent);
744}
745.footer-outer .widget h2 {
746color: #fff;
747}
748/* Sidebar
749----------------------------------------------- */
750#sidebar-left-1 {
751position: fixed;
752top: 0;
753left: 0;
754z-index: 1000;
755width: 332px;
756height: 100%;
757margin-right: 0 !important;
758margin-left: 0;
759background: var(--blog-sidebar) !important;
760border-right: 1px solid var(--blog-line);
761box-shadow: none;
762font-size: 16px;
763scrollbar-width: thin;
764}
765#sidebar-left-1 .widget {
766box-sizing: border-box;
767}
768#HTML2 {
769margin-bottom: 0;
770overflow: hidden;
771}
772#HTML2 img {
773display: block;
774width: 100% !important;
775max-width: 100%;
776height: auto !important;
777}
778#Header1 {
779margin-top: 10px;
780padding-right: 24px !important;
781padding-left: 24px !important;
782}
783#Header1 .title {
784line-height: 1.15;
785}
786#PageList1 {
787padding-right: 20px;
788padding-left: 20px;
789}
790#HTML5,
791#HTML8,
792.PopularPosts {
793padding-right: 24px !important;
794padding-left: 24px !important;
795}
796#HTML8 a {
797color: #000;
798font-size: 14px;
799}
800#HTML8 a:hover {
801color: #921;
802}
803#HTML8 img {
804display: block;
805width: 100% !important;
806height: auto !important;
807border-radius: 9px;
808}
809#PageList1 h2,
810.PopularPosts h2 {
811color: #666464;
812font-size: 20px;
813font-weight: 700;
814letter-spacing: 0.9px;
815text-transform: uppercase;
816}
817#PageList1 h2 {
818padding-top: 23px;
819}
820#PageList1 a,
821.PopularPosts a {
822color: #000;
823line-height: 22px;
824}
825#PageList1 a:hover,
826.PopularPosts a:hover {
827color: #921;
828}
829#PageList1 li {
830margin-bottom: 8px;
831}
832#PopularPosts1 ul {
833padding-left: 0 !important;
834list-style: none;
835}
836#PopularPosts1 li {
837margin-bottom: 12px !important;
838}
839#PopularPosts1 a {
840font-size: 15px;
841line-height: 1.35;
842}
843#PopularPosts1 li:nth-child(n + 7) {
844display: none;
845}
846/* Utility icons and status messages
847----------------------------------------------- */
848.icon {
849position: absolute;
850top: 2px;
851left: -26px;
852display: inline-block;
853}
854.icon-bs,
855.icon-popular,
856.icon-fav {
857width: 24px;
858height: 24px;
859margin-top: -2px;
860vertical-align: middle;
861background-repeat: no-repeat;
862background-size: cover;
863}
864.icon-bs {
865background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAnMIS51LYvy_X2RAKyu74LUGACiYTWPIQM5xozw2qpKIuroP6-UrE5HAcpwpc8KOBNLy9jnIYrn8TFzt-XkOL7p8KcRp5Dq9um_HXxLpdf2BgNjR3MeLoADA-8qkKFfqqUeIP3GAcoXSE/s1600/icon_bs.png);
866}
867.icon-labels {
868position: relative;
869top: 0;
870left: 0;
871display: inline-block;
872width: 9px;
873height: 14px;
874margin-top: -2px;
875vertical-align: middle;
876background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5F6T5eQNOrgTB3KJAKqdhSCD1sb62YAyoaXdZ-i3G5HX5IcYG89Ryb7VAezs9tBjbpJDcb36kILVRuKc7FRcLUNHV1paC435cU5AKth_X4EG4fx9Tfx7wdioBAkUHgOGkqt3K7zRzO33Q/s320/page-1.png) center / cover no-repeat;
877}
878.icon-popular {
879background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzHF_9b_n1_mJ9KuBm0Vzl7dtwdbk6o5WzVeqTAMPr120c4GABRLxRwc5gb9ASFrx013aciAlt8LM3BPWg9RC9gg0Z_IpSBwmIoAvd1N_bi6q_HEWOvErbbTwGnfBcq7bZrH-kYxywhJMO/s1600/icon_popular.png);
880}
881.icon-fav {
882background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuk8DqESwXpqGFsvpxn7MooP4Rbuim40hSZ41wWulOqKrsu0znix_LMGz1p4kzcSgoFajCNLZ3-s1o0P3XTO6rZQ2CFWrOSRVdVAysWKHoUldI3FEoedwOBujtM1zVWngSboVDEgBIHM5-/s1600/icon_fav.pn);
883}
884.status-msg-wrap1 {
885width: 100%;
886margin: 0 auto;
887color: #000;
888font-size: 20px;
889line-height: 1.2;
890text-align: left;
891}
892.status-msg-body1 {
893margin: 0 -20px 20px;
894padding: 15px 20px;
895background: #fff;
896border: 1px solid #e7e7e7;
897border-radius: 4px;
898}
899/* Blogger Lightbox
900----------------------------------------------- */
901.CSS_LIGHTBOX {
902position: fixed !important;
903inset: 0 !important;
904z-index: 2147483000 !important;
905width: auto !important;
906height: auto !important;
907max-width: none !important;
908}
909.CSS_LIGHTBOX .goog-inline-block .goog-inline-block {
910margin-left: 0 !important;
911}
912.CSS_LIGHTBOX .CSS_LIGHTBOX_BG_MASK {
913position: absolute !important;
914inset: 0 !important;
915width: 100% !important;
916height: 100% !important;
917}
918.CSS_LIGHTBOX .CSS_LIGHTBOX_SCALED_IMAGE_IMG {
919max-width: calc(100vw - 32px) !important;
920max-height: calc(100vh - 84px) !important;
921max-height: calc(100dvh - 84px) !important;
922object-fit: contain !important;
923}
924.CSS_LIGHTBOX .CSS_LIGHTBOX_BTN_CLOSE {
925position: fixed !important;
926top: max(8px, env(safe-area-inset-top)) !important;
927right: max(8px, env(safe-area-inset-right)) !important;
928z-index: 2147483001 !important;
929}
930/* Responsive images
931----------------------------------------------- */
932@media only screen and (max-width: 1200px) {
933.image-left.clear1200,
934.image-right.clear1200 {
935display: block;
936float: none;
937margin-right: 0;
938margin-left: 0;
939}
940}
941@media only screen and (max-width: 1240px) {
942.tabs-inner .widget li a {
943margin-right: 8px;
944}
945}
946@media only screen and (max-width: 1000px) {
947.image-left.clear1000,
948.image-right.clear1000 {
949display: block;
950float: none;
951margin-right: 0;
952margin-left: 0;
953}
954.content-inner {
955padding: 0 25px !important;
956}
957.tabs .widget li {
958float: none;
959}
960}
961/* Mobile
962----------------------------------------------- */
963@media only screen and (max-width: 960px) {
964html,
965body {
966max-width: 100%;
967overflow-x: hidden;
968}
969#sidebar-left-1 {
970box-sizing: border-box;
971width: 100% !important;
972min-width: 0 !important;
973height: 72px !important;
974margin: 0 !important;
975overflow: hidden !important;
976background: rgba(255, 255, 255, 0.95) !important;
977border-right: 0;
978border-bottom: 1px solid var(--blog-line);
979box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
980-webkit-backdrop-filter: blur(12px);
981backdrop-filter: blur(12px);
982}
983#HTML2,
984#HTML5,
985#HTML8,
986#PageList1,
987#PopularPosts1 {
988display: none !important;
989}
990#Header1 {
991box-sizing: border-box;
992float: none !important;
993width: 100% !important;
994margin: 0 !important;
995padding: 10px 18px !important;
996}
997#Header1 .title {
998font-size: 20px !important;
999}
1000#Header1 .description {
1001color: var(--blog-muted);
1002font-size: 14px !important;
1003}
1004.content-inner {
1005box-sizing: border-box;
1006width: 100%;
1007padding: 88px 18px 32px !important;
1008}
1009.tabs-outer {
1010margin-bottom: 22px;
1011overflow-x: auto;
1012scrollbar-width: none;
1013-webkit-overflow-scrolling: touch;
1014}
1015.tabs-outer::-webkit-scrollbar {
1016display: none;
1017}
1018.tabs-inner .section {
1019padding-top: 5px;
1020padding-bottom: 5px;
1021padding-left: inherit !important;
1022}
1023#PageList2 .widget-content {
1024width: max-content;
1025max-width: none;
1026margin: 0 !important;
1027}
1028#PageList2 .widget-content ul {
1029flex-wrap: nowrap !important;
1030gap: 20px;
1031}
1032#PageList2 .widget-content li {
1033flex: 0 0 auto;
1034}
1035#PageList2 .widget-content a {
1036font-size: 15px;
1037white-space: nowrap;
1038}
1039.main-inner {
1040margin-top: 20px !important;
1041padding: 0 !important;
1042}
1043.main-inner .columns {
1044box-sizing: border-box;
1045width: 100%;
1046padding-right: 0 !important;
1047padding-left: 0 !important;
1048}
1049.main.section {
1050margin-right: 0 !important;
1051margin-left: 0 !important;
1052}
1053.blog-posts {
1054width: 100% !important;
1055max-width: none !important;
1056margin: 0 !important;
1057}
1058.date-outer {
1059margin-bottom: 60px;
1060}
1061.post-outer {
1062box-sizing: border-box;
1063width: 100%;
1064margin: 0 0 44px !important;
1065padding: 0 0 44px !important;
1066border-bottom: 1px solid var(--blog-line);
1067}
1068.post,
1069.post-body {
1070width: 100%;
1071max-width: 100%;
1072}
1073h1.post-title,
1074h3.post-title {
1075overflow-wrap: anywhere;
1076font-size: clamp(29px, 8vw, 34px);
1077line-height: 1.14;
1078}
1079.post-body {
1080overflow-wrap: anywhere;
1081font-size: 18px;
1082line-height: 1.65;
1083}
1084.post-body blockquote {
1085margin: 24px 0 !important;
1086padding: 16px 18px !important;
1087}
1088.post-body img {
1089max-width: 100%;
1090height: auto;
1091border-radius: 8px;
1092}
1093.post-body iframe {
1094width: 100%;
1095max-width: 100%;
1096}
1097.post-body pre,
1098.post-body table {
1099max-width: 100%;
1100overflow-x: auto;
1101}
1102#blog-pager {
1103flex-direction: column;
1104}
1105#blog-pager a {
1106justify-content: center;
1107text-align: center;
1108}
1109}
1110@media (prefers-reduced-motion: reduce) {
1111*,
1112*::before,
1113*::after {
1114scroll-behavior: auto !important;
1115transition: none !important;
1116}
1117}
1118--></style>
1119<link href='https://www.blogger.com/dyncss/458002489272917533/authorization.css?zx=c0cb7e41-e869-4202-b210-b87ba99eaf8f' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyncss/458002489272917533/authorization.css?zx=c0cb7e41-e869-4202-b210-b87ba99eaf8f' rel='stylesheet'/></noscript>
1120<meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/>
1121<meta name='google-adsense-platform-domain' content='blogspot.com'/>
1122
1123</head>
1124<body class='loading'>
1125<div class='body-fauxcolumns'>
1126<div class='fauxcolumn-outer body-fauxcolumn-outer'>
1127<div class='cap-top'>
1128<div class='cap-left'></div>
1129<div class='cap-right'></div>
1130</div>
1131<div class='fauxborder-left'>
1132<div class='fauxborder-right'></div>
1133<div class='fauxcolumn-inner'>
1134</div>
1135</div>
1136<div class='cap-bottom'>
1137<div class='cap-left'></div>
1138<div class='cap-right'></div>
1139</div>
1140</div>
1141</div>
1142<div class='content'>
1143<div class='content-fauxcolumns'>
1144<div class='fauxcolumn-outer content-fauxcolumn-outer'>
1145<div class='cap-top'>
1146<div class='cap-left'></div>
1147<div class='cap-right'></div>
1148</div>
1149<div class='fauxborder-left'>
1150<div class='fauxborder-right'></div>
1151<div class='fauxcolumn-inner'>
1152</div>
1153</div>
1154<div class='cap-bottom'>
1155<div class='cap-left'></div>
1156<div class='cap-right'></div>
1157</div>
1158</div>
1159</div>
1160<div class='content-outer'>
1161<div class='content-cap-top cap-top'>
1162<div class='cap-left'></div>
1163<div class='cap-right'></div>
1164</div>
1165<div class='fauxborder-left content-fauxborder-left'>
1166<div class='fauxborder-right content-fauxborder-right'></div>
1167<div class='content-inner'>
1168<header>
1169<div class='header-outer'>
1170<div class='header-cap-top cap-top'>
1171<div class='cap-left'></div>
1172<div class='cap-right'></div>
1173</div>
1174<div class='fauxborder-left header-fauxborder-left'>
1175<div class='fauxborder-right header-fauxborder-right'></div>
1176<div class='region-inner header-inner'>
1177<div class='header no-items section' id='header'></div>
1178</div>
1179</div>
1180<div class='header-cap-bottom cap-bottom'>
1181<div class='cap-left'></div>
1182<div class='cap-right'></div>
1183</div>
1184</div>
1185</header>
1186<div class='tabs-outer'>
1187<div class='tabs-cap-top cap-top'>
1188<div class='cap-left'></div>
1189<div class='cap-right'></div>
1190</div>
1191<div class='fauxborder-left tabs-fauxborder-left'>
1192<div class='fauxborder-right tabs-fauxborder-right'></div>
1193<div class='region-inner tabs-inner'>
1194<div class='tabs section' id='crosscol'><div class='widget PageList' data-version='1' id='PageList2'>
1195<h2>Страницы</h2>
1196<div class='widget-content'>
1197<ul>
1198<li>
1199<a href='https://blog.byndyu.ru/'>Последние статьи</a>
1200</li>
1201<li>
1202<a href='https://blog.byndyu.ru/p/blog-page_19.html'>IT-архитектура</a>
1203</li>
1204<li>
1205<a href='https://blog.byndyu.ru/p/blog-page_4.html'>Управление</a>
1206</li>
1207<li>
1208<a href='https://blog.byndyu.ru/p/blog-page_95.html'>
1208Инженерные практики</a>
1209</li>
1210<li>
1211<a href='https://blog.byndyu.ru/p/blog-page_24.html'>Образование и карьера</a>
1212</li>
1213</ul>
1214<div class='clear'></div>
1215</div>
1216</div></div>
1217<div class='tabs section' id='crosscol-overflow'><div class='widget HTML' data-version='1' id='HTML1'>
1218<div class='widget-content'>
1219<!-- Yandex.Metrika counter -->
1220<script type="text/javascript">
1221    (function(m,e,t,r,i,k,a){
1222        m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
1223        m[i].l=1*new Date();
1224        for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
1225        k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
1226    })(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=105333143', 'ym');
1227
1228    ym(105333143, 'init', {ssr:true, webvisor:true, clickmap:true, ecommerce:"dataLayer", accurateTrackBounce:true, trackLinks:true});
1229</script>
1229
1230<noscript><div><img src="https://mc.yandex.ru/watch/105333143" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
1231<!-- /Yandex.Metrika counter -->
1232</div>
1233<div class='clear'></div>
1234</div></div>
1235</div>
1236</div>
1237<div class='tabs-cap-bottom cap-bottom'>
1238<div class='cap-left'></div>
1239<div class='cap-right'></div>
1240</div>
1241</div>
1242<div class='main-outer'>
1243<div class='main-cap-top cap-top'>
1244<div class='cap-left'></div>
1245<div class='cap-right'></div>
1246</div>
1247<div class='fauxborder-left main-fauxborder-left'>
1248<div class='fauxborder-right main-fauxborder-right'></div>
1249<div class='region-inner main-inner'>
1250<div class='columns fauxcolumns'>
1251<div class='fauxcolumn-outer fauxcolumn-center-outer'>
1252<div class='cap-top'>
1253<div class='cap-left'></div>
1254<div class='cap-right'></div>
1255</div>
1256<div class='fauxborder-left'>
1257<div class='fauxborder-right'></div>
1258<div class='fauxcolumn-inner'>
1259</div>
1260</div>
1261<div class='cap-bottom'>
1262<div class='cap-left'></div>
1263<div class='cap-right'></div>
1264</div>
1265</div>
1266<div class='fauxcolumn-outer fauxcolumn-left-outer'>
1267<div class='cap-top'>
1268<div class='cap-left'></div>
1269<div class='cap-right'></div>
1270</div>
1271<div class='fauxborder-left'>
1272<div class='fauxborder-right'></div>
1273<div class='fauxcolumn-inner'>
1274</div>
1275</div>
1276<div class='cap-bottom'>
1277<div class='cap-left'></div>
1278<div class='cap-right'></div>
1279</div>
1280</div>
1281<div class='fauxcolumn-outer fauxcolumn-right-outer'>
1282<div class='cap-top'>
1283<div class='cap-left'></div>
1284<div class='cap-right'></div>
1285</div>
1286<div class='fauxborder-left'>
1287<div class='fauxborder-right'></div>
1288<div class='fauxcolumn-inner'>
1289</div>
1290</div>
1291<div class='cap-bottom'>
1292<div class='cap-left'></div>
1293<div class='cap-right'></div>
1294</div>
1295</div>
1296<!-- corrects IE6 width calculation -->
1297<div class='columns-inner'>
1298<div class='column-center-outer'>
1299<div class='column-center-inner'>
1300<div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'>
1301<div class='blog-posts hfeed'>
1302
1303          <div class="date-outer">
1304        
1305
1306          <div class="date-posts">
1307        
1308<div class='post-outer'>
1309<div class='post hentry'>
1310<a data-qa='!!!' name='2002061643571794461'></a>
1311<h3 class='post-title entry-title '>
1312<a href='https://blog.byndyu.ru/2008/12/blog-post.html'>Технические долги</a>
1313</h3>
1314<div class='post-header'>
1315<div class='post-header-line-1'>
1316<h2 class='date-header'><span>4 декабря 2008&#8239;г.</span></h2>
1317</div>
1318</div>
1319<div class='post-body entry-content'>
1320<p>Этот термин впервые ввел <a href="http://en.wikipedia.org/wiki/Technical_debt">Ward Cunningham</a>:</p>
1321
1322<ul>
1323<li>Технические долги включают ту работу в проекте, которую мы решаем (хорошо, если осознанно) не делать в данный момент, но которая будет мешать развитию проекта в дальнейшем, если не будет выполнена.</li>
1324<li>Технические долги не включают отложенную функциональность, которая была бы хорошим дополнением к проекту, но в данный момент имеет низкий приоритет (например, улучшенный интерфейс пользователя). Кроме этого, тех. долги это не баги.</li>
1325</ul>
1326
1327<a name="more"></a>
1328
1329<blockquote>
1330<p>Обсуждение нюансов технических долгов в подкасте Podlodka <a href="https://disk.yandex.ru/d/QWEBpcS2MJV5UA">https://soundcloud.com/podlodka/podlodka-77-tekhnicheskiy-dolg</a></p>
1331</blockquote>
1332
1333<p>Понять действия, которые приводят к долгам в коде очень легко, потому что каждый из нас делает эти долги изо дня в день. Саму систему появления этих долгов можно описать с помощью денежной <a href="http://www.c2.com/cgi/wiki?ComplexityAsDebt">метафоры</a>:</p>
1334
1335<ul>
1336<li>Игнорировать дизайн &mdash; брать деньги в долг</li>
1337<li>Рефакторинг &mdash; способ возврата долга</li>
1338<li>Замедление разработки из-за запутанности системы &mdash; выплата процентов</li>
1339<li>Провал проекта &mdash; приезд приставов и конец бизнеса.</li>
1340</ul>
1341
1342<h2 class="post-inner-title">Типы долгов</h2>
1343
1344<p>В общем, все долги в коде можно разделить на <a href="http://www.construx.com/10x_
1344Software_Development/Technical_Debt/">несколько категорий</a>. Все они разные по сути и по ущербу, который наносят, но конечный результат их действия на проект один и тот же &mdash; повышение затрат на разработку приложения.</p>
1345
1346<h3 class="post-inner-title">Неумышленные</h3>
1347
1348<p>Это самый простой и очевидный тип долгов. Они накапливаются, если программист делает ошибки при разработке проекта, неверно применяя шаблоны проектирования или неправильно используя принципы ООП.</p>
1349<p>В тоже время, это самый опасный тип долгов, т.к. разработчики не видят рисков. Они не могут правильно оценивать время на добавление новой функциональности или реорганизации уже работающей системы.</p>
1350
1351<h3 class="post-inner-title">Умышленные</h3>
1352
1353<p>Это долги, которые характерны для более &#171;матерых&#187; программистов.</p>
1354
1355<h4 class="post-inner-title">Кратковременные</h4>
1356
1357<p>При разработке проекта, мы всегда стараемся оставить его в положении наиболее выгодном для будущих изменений. Сделать ее более гибкой. Но большинство из нас пишет код для коммерческого использования. В условиях конкуренции нужно завоевывать рынки и опережать конкурентов бизнеса, на который мы работаем. Поэтому, когда сроки поджимают, руководитель проекта слышать не хочет про качественный код, ему нужен результат, причем <i>быстро</i>. Мы начинаем действительно <i>быстро</i> писать код. Оставлять дублирование, не писать тесты, использовать магические числа в коде в надежде, что после выхода очередной версии продукта мы это все исправим. Но правда в том, что <a href="http://vanryswyckjan.blogspot.com/2008/11/professional-under-pressure.html">мы этого никогда не исправим</a>. Ни после этой версии, ни после какой-то другой. К тому же, если мы опустили планку качества в проекте, то эта планка будет <a href="https://en.wikipedia.org/wiki/Broken_windows_theory">падать с ускорением все ниже и ниже</a>.</p>
1358
1359<p style="font-weight: bold;"><span style="font-size:100%;">Долговременные</span></p>
1360<p>Эти долги лежат у самого основания нашего проекта. С ними мы миримся и договариваемся, что они являются нормой. К примеру, мы не будем поддерживать Oracle ни в какой версии нашей системы. С таким утверждением можно вполне спокойно развивать проект. Или например, система будет иметь пользовательский интерфейс на ASP.NET. Если приходится платить по этим долгам (например, переход с MS SQL на Oracle), то в конечном счете это означает создание качественно нового приложения.</p>
1361
1362<h2 class="post-inner-title">&#171;Запах&#187; кода с долгами</h2>
1363
1364<p>В вашем, в моем и любом другом проекте есть долги. Вопрос в том, на сколько сильно они влияют на разработку в данный момент. Существует критический порог, за который не стоит заходить. Об этом немного по позже. Чтобы понять, что вы приближаетесь к неминуемому провалу проекта, обратите внимание на эти признаки:
1365</p><ol><li>   <span style="font-weight: bold;">Любое изменение системы приводит к ряду новых дефектов.</span> Запутанность в коде, сильное связывание всех частей проекта, отсутствие тестов приводит к эффекту бабочки. Когда, к примеру, изменение способа отправки электронных писем влияет на работу слоя отображения. В таком проекте трудно двигаться вперед. При интенсивной разработке постоянно будут вылезать недоработки или поломки в некогда работающем коде.</li><li>   <span style="font-weight: bold;">Команда разработчиков постоянно встречается с непредвиденными проблемами.</span> Это могут проблемы разного характера. Например, невозможность расширения иерархии объектов, проблемы с переходом на другой провайдер по передаче SMS сообщений. Если дизайн системы не предполагает ее изменения в дальнейшем (сильное связывание компонентов, раскрытие внутренностей объектов, глобаÐ
1365»ÑŒÐ½Ñ‹Ðµ переменные и т.п.), то это всегда будет приводить разработчиков к неожиданным затруднениям.</li><li>   <span style="font-weight: bold;">Уже исправленные дефекты снова появляются.</span> Обычно это происходит, когда нет модульных тестов. Причины вполне очевидны. Если мы нашли ошибку в программе, например, отсутствие проверки на граничные значения, и написали на эту ошибку тест, то теперь на протяжении жизни проекта этот тест будет гарантировать, что такая ошибка вновь не появится. Неверное исправление кода приведет к падению теста. Если же такого теста нет и ваш коллега поправил код так, как ему этого хочется, то ошибка может вернуться опять. Ему ведь никто не сообщил, что в таком-то модуле надо обязательно проверять значение на верхнюю границу.</li></ol>
1366
1367<h2 class="post-inner-title">Когда начинаем платить?</h2>
1368
1369<p>Интересно рассмотреть влияние долгов на развитие проекта в динамике. И наибольший интерес представляет <a href="http://martinfowler.com/bliki/DesignStaminaHypothesis.html">сравнение двух разных подходов</a>: разработка проекта с хорошим дизайном и без него.</p>
1370
1371<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s1600/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="549" data-original-width="1004" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s1600/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg"/></a></div>
1372
1373<p>На рисунке показана скорость, с которой команды наращивают функциональность в проекте. Команда синих забыла про дизайн и про тесты. Она решила в кратчайший срок добиться впечатляющих результатов.</p>
1374<p>Команда красных идет проверенной дорогой. Они уделяют особое внимание качеству кода, пишут тесты и заботятся о расширяемости системы.</p>
1375<p>Как можно увидеть, команда синих довольно значительно обошла команду красных по скорости в начале. Но, со временем, их продуктивность падает. Дело в том, что они начинают тратить дополнительное время на поддержку системы. Без модульных тестов довольно трудно двигаться вперед. Если команда синих состоит больше чем из одного человека, то замедление наступит гораздо раньше.</p>
1376<p>В это время команда красных уверенно и <i>равномерно </i>идет вверх.
1377Точка пересечения производительности двух команд &mdash; время, когда команда синих начинает платить за долги в коде.</p>
1378<p>Напрашивается простое решение &mdash; когда синяя команда начинает платить за долги, ей нужно перепрыгнуть на путь красной команды. К сожалению, в этот момент уже слишком поздно надеяться на получение стабильного роста, т.к. долги в коде дадут о себе знать.</p>
1379<p>Отсюда можно сделать вывод, что если команде нужно сделать &#171;быстрый&#187; продукт (например, промо-версию своего продукта для демонстрации и получения инвестиций на основной проект), то вполне подойдет тактика синей команды. Однако, с такой тактикой не стоит рассчитывать на длительные проекты.</p>
1380
1381<h2 class="post-inner-title">Динамика нарастания долгов</h2>
1382
1383<p>Теперь рассмотрим динамику нарастания долгов и их оплату <i>реальными</i> деньгами. Закрашенная серая площадь показывает общую сумму, которую потратили не на сам проект, а на оплату за технические долги.</p>
1384
1385<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQx1k5RTZ81Wh74GIhWYvlrZjtMejhPlybftpzMY-aeUoChFwZPViugR2jCaw9uJmlS3xbuHH8IgvwRP4ktz4-VH4-UM0pONPZiDdB5XQRz0HHi3AQu2crVhJTvl-f4brj6JGiV8FLjFceZazU2TlvYvnHlOKlPbf5W-3C-OkdUXUCh5FwHUEYZe9c2w/s1600/%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D0%BA%D0%B0%20%281%29.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="540" data-original-width="862" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQx1k5RTZ81Wh74GIhWYvlrZjtMejhPlybftpzMY-aeUoChFwZPViugR2jCaw9uJmlS3xbuHH8IgvwRP4ktz4-VH4-UM0pONPZiDdB5XQRz0HHi3AQu2crVhJTvl-f4brj6JGiV8FLjFceZazU2TlvYvnHlOKlPbf5W-3C-OkdUXUCh5FwHUEYZe9c2w/s1600/%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D0%BA%D0%B0%20%281%29.jpg"/></a></div>
1386
1387<p>Рисунок показывает на сколько больше денег было потрачено на проект из-за долгов в коде.</p>
1388
1389<p>Интересно отметить тенденции:</p>
1390<ul><li>До первого релиза проекта идет интенсивное наращивание функциональности. Работа кипит. </li><li>В какой-то момент (первая красная точка) программисты понимают, что без улучшения качества кода будет трудно двигаться вперед. Этот момент показывает спад долгов в коде (до первой зеленой точки). </li><li>Перед релизом приходит руководитель проекта и начинает подгонять команду, напоминать о приближающихся сроках или, что еще хуже, эти сроки урезать. Здесь мы видим резкий скачок. В этот момент увеличивается как само количество долгов в коде, так и выплаты по уже существующим.</li></ul>
1391
1392<p>Эта тенденция повторяется от релиза к релизу. Чем больше мы работаем с проектом, тем больше мы платим за оставленные в коде долги.</p>
1393
1394<h2 class="post-inner-title">Почему руководители допускают тех. долг</h2>
1395
1396<p>Почему же при таком очевидном ходе вещей руководители ничего не предпринимают? Почему они позволяют себе тратить деньги  не на создание новых функций, а на оплату технических долгов снова и снова?</p>
1397
1398<p>Для ответа на эти вопросы давайте представим себе точки зрения на эту проблему программистов и руководителей.</p>
1399
1400<h3 class="post-inner-title">Программисты видят <i>причину</i></h3>
1401
1402<p>Сами создатели программы знают, что им мешает двигаться вперед. Они каждый день видят магические числа в коде, дублирование кода, отсутствие тестов, соглашаются с временными заглушками в коде. Но по разным причинам стараются это игнорировать.</p>
1403
1404<h3 class="post-inner-title">Руководители видят <i>следствия</i></h3>
1405
1406<p>Невозможно объяснить человеку, который не разбирается в программировании, почему мы в данный момент не можем позволить себе расширить нашу систему? Или почему вдруг стоимость поддержки системы стала расти? И почему нам требуется все больше и больше времени на добавление функций, которые раньше довольно быстро добавлялись? Попробуйте объяснить это в теÑ
1406…нических терминах и вас попросят вернуться к работе и впредь не допускать подобных ситуаций. В этот момент время уже проиграно. Теперь, чтобы догнать конкурентов, нужно сменить тактику!</p>
1407
1408<p>Если вы хотите открыть глаза на существование этой проблемы вашему руководителю, вам придется говорить с ним с позиций его прибыли.</p>
1409
1410<h2 class="post-inner-title">Сравнение подходов</h2>
1411
1412<p>Теперь рассмотрим различные подходы к разработке в ещё более длительном промежутке времени.</p>
1413
1414<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFwgSFvJitsZODUP7iqfEiPiWOKwQS8S7oRx_mYb6YKMYA7uRMECvmpVjrp9zdt60ZNSRkjpjb_NieIawKK38OpRpqKsQMNYTMAB8mS3-umMwSsKGp-QhLydax44jynUFZfrYCzvSq-QmB5VJJJ-e-EcVXBXsPyLkYNvDpShUXR3F8fTPBA1-SYcjVFA/s1600/%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%281%29.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" data-original-height="678" data-original-width="1056" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFwgSFvJitsZODUP7iqfEiPiWOKwQS8S7oRx_mYb6YKMYA7uRMECvmpVjrp9zdt60ZNSRkjpjb_NieIawKK38OpRpqKsQMNYTMAB8mS3-umMwSsKGp-QhLydax44jynUFZfrYCzvSq-QmB5VJJJ-e-EcVXBXsPyLkYNvDpShUXR3F8fTPBA1-SYcjVFA/s1600/%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%281%29.jpg"/></a></div>
1415
1416<p>Для сравнения у нас есть 3 подхода:
1417</p><ol><li><span style="font-weight: bold;">Команда не заботится о качестве кода.</span> Как уже было показано, этот способ вести проект ведет только к его полной остановке. Наступает момент, когда проект проще выкинуть в окно и написать заново.</li><li><span style="font-weight: bold;">Руководители, зная как важно улучшать код, раз в год выделяют пару недель на рефакторинг.</span> Слишком редкие возможности действительно улучшить код в проекте не дадут практически никаких результатов. Долги растут постоянно. Если оплачивать их только иногда, мы никогда не добьемся их уменьшения.</li><li><span style="font-weight: bold;">Команда заботится о постоянном улучшении качества кода. </span>Только постоянная забота о качестве кода может на долгое время сохранить систему в рабочем состоянии.</li></ol>
1418
1419<h2 class="post-inner-title">Метрики технического долга</h2>
1420
1421<p>Прежде, чем снижать технический долг, его нужно посчитать. Не посчитанный долг разработчики будут снижать бесконечно и безрезультатно.</p>
1422
1423<p>Считают долг с помощью таких инструментов как <a href="https://www.sonarqube.org/">SonarQube</a>. Кроме этого, в системы CI бывают встроены метрики кода. Например, в <a href="https://confluence.jetbrains.com/display/TCD9/Code+Quality+Tools">TeamCity</a> есть анализаторы кода, счетчики модульных тестов и покрытия тестами.</p>
1424
1425<p>Если разработчики берут задачу по снижению технического долга, то логично, что после реализации задачи, снижение станет заметным на графиках и в цифрах.</p>
1426
1427<h2 class="post-inner-title">Как правильно относится к техническим долгам</h2>
1428
1429<p>Итак, из всего сказанного можно подытожить, что <b>технические долги == финансовые долги</b>.</p>
1430
1431<p>Технические долги придется оплачивать с процентами, причем <i>реальными</i> деньгами. Чем дольше мы будем тянуть с оплатой, тем выше будет выплата по долгу.</p>
1432
1433<p><b>Ссылки:</b></p>
1434<ul>
1435<li><a href="http://wiki.c2.com/?TechnicalDebt">http://wiki.c2.com/?TechnicalDebt</a></li>
1436<li><a href="https://www.youtube.com/watch?v=pqeJFYwnkjE">Ward Explains Debt Metaphor</a></li>
1437<li><a href="http://wiki.c2.com/?DesignDebt">http://wiki.c2.com/?DesignDebt</a></li>
1438<li><a href="https://en.wikipedia.org/wiki/Technical_debt">https://en.wikipedia.org/wiki/Technical_debt</a></li>
1439</ul>
1440<div style='clear: both;'></div>
1441</div>
1442<div class='post-footer'>
1443<div class='post-footer-line post-footer-line-1' style='display:none;'>
1444<span class='post-timestamp1'>
1445<abbr class='published' title='2008-12-04T23:11:00+05:00'>12/04/2008</abbr>
1446</span>
1447<span class='post-labels'>
1448<span class='post-author vcard'></span>
1449</span>
1450</div>
1451<div class='post-footer-line post-footer-line-2'>
1452<span class='post-backlinks post-comment-link'>
1453</span>
1454<span class='reaction-buttons'>
1455<i class='icon icon-labels'></i>
1456<a href='https://blog.byndyu.ru/search/label/Agile' rel='tag'>Agile</a>&#12539;
1457<a href='https://blog.byndyu.ru/search/label/Best%20Practices' rel='tag'>Best Practices</a>&#12539;
1458<a href='https://blog.byndyu.ru/search/label/Philosophy' rel='tag'>Philosophy</a>&#12539;
1459<a href='https://blog.byndyu.ru/search/label/TDD' rel='tag'>TDD</a>
1460</span>
1461<span class='post-icons'>
1462</span>
1463</div>
1464</div>
1465</div>
1466<div class='comments' id='comments'>
1467<a name='comments'></a>
1468<h4>12 комментариев:</h4>
1469<div class='comments-content'>
1470<script async='async' src='' type='text/javascript'></script>
vendor: 1 bytes, line 1470
1470
1471<script type='text/javascript'>
1472    (function() {
1473      var items = null;
1474      var msgs = null;
1475      var config = {};
1476
1477// <![CDATA[
1478      var cursor = null;
1479      if (items && items.length > 0) {
1480        cursor = parseInt(items[items.length - 1].timestamp) + 1;
1481      }
1482
1483      var bodyFromEntry = function(entry) {
1484        var text = (entry &&
1485                    ((entry.content && entry.content.$t) ||
1486                     (entry.summary && entry.summary.$t))) ||
1487            '';
1488        if (entry && entry.gd$extendedProperty) {
1489          for (var k in entry.gd$extendedProperty) {
1490            if (entry.gd$extendedProperty[k].name == 'blogger.contentRemoved') {
1491              return '<span class="deleted-comment">' + text + '</span>';
1492            }
1493          }
1494        }
1495        return text;
1496      }
1497
1498      var parse = function(data) {
1499        cursor = null;
1500        var comments = [];
1501        if (data && data.feed && data.feed.entry) {
1502          for (var i = 0, entry; entry = data.feed.entry[i]; i++) {
1503            var comment = {};
1504            // comment ID, parsed out of the original id format
1505            var id = /blog-(\d+).post-(\d+)/.exec(entry.id.$t);
1506            comment.id = id ? id[2] : null;
1507            comment.body = bodyFromEntry(entry);
1508            comment.timestamp = Date.parse(entry.published.$t) + '';
1509            if (entry.author && entry.author.constructor === Array) {
1510              var auth = entry.author[0];
1511              if (auth) {
1512                comment.author = {
1513                  name: (auth.name ? auth.name.$t : undefined),
1514                  profileUrl: (auth.uri ? auth.uri.$t : undefined),
1515                  avatarUrl: (auth.gd$image ? auth.gd$image.src : undefined)
1516                };
1517              }
1518            }
1519            if (entry.link) {
1520              if (entry.link[2]) {
1521                comment.link = comment.permalink = entry.link[2].href;
1522              }
1523              if (entry.link[3]) {
1524                var pid = /.*comments\/default\/(\d+)\?.*/.exec(entry.link[3].href);
1525                if (pid && pid[1]) {
1526                  comment.parentId = pid[1];
1527                }
1528              }
1529            }
1530            comment.deleteclass = 'item-control blog-admin';
1531            if (entry.gd$extendedProperty) {
1532              for (var k in entry.gd$extendedProperty) {
1533                if (entry.gd$extendedProperty[k].name == 'blogger.itemClass') {
1534                  comment.deleteclass += ' ' + entry.gd$extendedProperty[k].value;
1535                } else if (entry.gd$extendedProperty[k].name == 'blogger.displayTime') {
1536                  comment.displayTime = entry.gd$extendedProperty[k].value;
1537                }
1538              }
1539            }
1540            comments.push(comment);
1541          }
1542        }
1543        return comments;
1544      };
1545
1546      var paginator = function(callback) {
1547        if (hasMore()) {
1548          var url = config.feed + '?alt=json&v=2&orderby=published&reverse=false&max-results=50';
1549          if (cursor) {
1550            url += '&published-min=' + new Date(cursor).toISOString();
1551          }
1552          window.bloggercomments = function(data) {
1553            var parsed = parse(data);
1554            cursor = parsed.length < 50 ? null
1555                : parseInt(parsed[parsed.length - 1].timestamp) + 1
1556            callback(parsed);
1557            window.bloggercomments = null;
1558          }
1559          url += '&callback=bloggercomments';
1560          var script = document.createElement('script');
1561          script.type = 'text/javascript';
1562          script.src = url;
1563          document.getElementsByTagName('head')[0].appendChild(script);
1564        }
1565      };
1566      var hasMore = function() {
1567        return !!cursor;
1568      };
1569      var getMeta = function(key, comment) {
1570        if ('iswriter' == key) {
1571          var matches = !!comment.author
1572              && comment.author.name == config.authorName
1573              && comment.author.profileUrl == config.authorUrl;
1574          return matches ? 'true' : '';
1575        } else if ('deletelink' == key) {
1576          return config.baseUri + '/delete-comment.g?blogID='
1577               + config.blogId + '&postID=' + comment.id;
1578        } else if ('deleteclass' == key) {
1579          return comment.deleteclass;
1580        }
1581        return '';
1582      };
1583
1584      var replybox = null;
1585      var replyUrlParts = null;
1586      var replyParent = undefined;
1587
1588      var onReply = function(commentId, domId) {
1589        if (replybox == null) {
1590          // lazily cache replybox, and adjust to suit this style:
1591          replybox = document.getElementById('comment-editor');
1592          if (replybox != null) {
1593            replybox.height = '250px';
1594            replybox.style.display = 'block';
1595            replyUrlParts = replybox.src.split('#');
1596          }
1597        }
1598        if (replybox && (commentId !== replyParent)) {
1599          replybox.src = '';
1600          document.getElementById(domId).insertBefore(replybox, null);
1601          replybox.src = replyUrlParts[0]
1602              + (commentId ? '&parentID=' + commentId : '')
1603              + '#' + replyUrlParts[1];
1604          replyParent = commentId;
1605        }
1606      };
1607
1608      var hash = (window.location.hash || '#').substring(1);
1609      var startThread, targetComment;
1610      if (/^comment-form_/.test(hash)) {
1611        startThread = hash.substring('comment-form_'.length);
1612      } else if (/^c[0-9]+$/.test(hash)) {
1613        targetComment = hash.substring(1);
1614      }
1615
1616      // Configure commenting API:
1617      var configJso = {
1618        'maxDepth': config.maxThreadDepth
1619      };
1620      var provider = {
1621        'id': config.postId,
1622        'data': items,
1623        'loadNext': paginator,
1624        'hasMore': hasMore,
1625        'getMeta': getMeta,
1626        'onReply': onReply,
1627        'rendered': true,
1628        'initComment': targetComment,
1629        'initReplyThread': startThread,
1630        'config': configJso,
1631        'messages': msgs
1632      };
1633
1634      var render = function() {
1635        if (window.goog && window.goog.comments) {
1636          var holder = document.getElementById('comment-holder');
1637          window.goog.comments.render(holder, provider);
1638        }
1639      };
1640
1641      // render now, or queue to render when library loads:
1642      if (window.goog && window.goog.comments) {
1643        render();
1644      } else {
1645        window.goog = window.goog || {};
1646        window.goog.comments = window.goog.comments || {};
1647        window.goog.comments.loadQueue = window.goog.comments.loadQueue || [];
1648        window.goog.comments.loadQueue.push(render);
1649      }
1650    })();
1651// ]]>
1652  </script>
1652
1653<div id='comment-holder'>
1654<div class="comment-thread toplevel-thread"><ol id="top-ra"><li class="comment" id="c322450092776485216"><div class="avatar-image-container"><img src="//www.blogger.com/img/blogger_logo_round_35.png" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="https://www.blogger.com/profile/03092956574591191608" rel="nofollow">Unknown</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1297354719189#c322450092776485216">10 февраля 2011&#8239;г. в 21:18</a></span></div><p class="comment-content">Респект!<br>Занимательно... Думаю что каждый увидит как минимум один из своих проектов в другом свете...</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="322450092776485216">Ответить</a><span class="item-control blog-admin blog-admin pid-1132921324"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/322450092776485216">Удалить</a></span></span></div><div class="comment-replies"><div id="c322450092776485216-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c322450092776485216-ra" class="thread-chrome thread-expanded"><div></div><div id="c322450092776485216-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="322450092776485216">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c322450092776485216-ce"></div></li><li class="comment" id="c5362762054431744641"><div class="avatar-image-container"><img src="//www.blogger.com/img/blogger_logo_round_35.png" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="https://www.blogger.com/profile/01900895412604739603" rel="nofollow">Елена</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1307723551836#c5362762054431744641">10 июня 2011&#8239;г. в 22:32</a></span></div><p class="comment-content">В неумышленных долгах ошибка &quot;при разработкЕ&quot;.<br>И еще в предложениях: &quot;При разработке проекта, мы всегда стараемся оставить ее в положении наиболее выгодном для будущих изменений. Сделать ее более гибкой.&quot;, наверное нужно &quot;его&quot; вместо &quot;ее&quot;.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="5362762054431744641">Ответить</a><span class="item-control blog-admin blog-admin pid-347671927"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/5362762054431744641">Удалить</a></span></span></div><div class="comment-replies"><div id="c5362762054431744641-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c5362762054431744641-ra" class="thread-chrome thread-expanded"><div></div><div id="c5362762054431744641-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="5362762054431744641">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c5362762054431744641-ce"></div></li><li class="comment" id="c1395340432446027673"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Андрей Максимов</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1347939456894#c1395340432446027673">18 сентября 2012&#8239;г. в 09:37</a></span></div><p class="comment-content">Хорошая статья, но непонятно, что делать в случаях, когда долги растут. Начинать с нуля? А что если результат и изменения нужны постоянно?<br>Как понятно по вопросам, я спрашиваю в роли руководителя проекта.  </p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="1395340432446027673">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/1395340432446027673">Удалить</a></span></span></div><div class="comment-replies"><div id="c1395340432446027673-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c1395340432446027673-ra" class="thread-chrome thread-expanded"><div></div><div id="c1395340432446027673-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="1395340432446027673">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c1395340432446027673-ce"></div></li><li class="comment" id="c4500075387044332797"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="http://www.facebook.com/alexander.byndyu" rel="nofollow">Alexander  Byndyu</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1347941819817#c4500075387044332797">18 сентября 2012&#8239;г. в 10:16</a></span></div><p class="comment-content">Андрей,<br><br><br>Начинать с нуля, конечно, не нужно :) Вы можете давать результат постоянно, если программисты научатся правильно делать рефакторинг.<br><br><br>Я не видел ваш проект, но если он был сделан с соблюдением принципов проектирования, то рефакторинг может идти параллельно с разработкой.<br><br><br>Если проект представляет из себя сплошной теÑ
1654…. долг, то вы должны понимать, что рано или поздно добавить в проект уже ничего не получится и вот тогда надо будет переписывать с нуля.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="4500075387044332797">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/4500075387044332797">Удалить</a></span></span></div><div class="comment-replies"><div id="c4500075387044332797-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c4500075387044332797-ra" class="thread-chrome thread-expanded"><div></div><div id="c4500075387044332797-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="4500075387044332797">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c4500075387044332797-ce"></div></li><li class="comment" id="c8176250518626007878"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Андрей Максимов</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1354281253726#c8176250518626007878">30 ноября 2012&#8239;г. в 19:14</a></span></div><p class="comment-content">Я думаю, что такого не бывает - когда проект - сплошной долг. По крайней мере, никто не признается...<br>Тут каждый наверное сам должен определять, потому что со стороны возможно давать лишь абстрактные советы.<br>Где-то есть принципы, где-то нет... В общем, мы делаем изменения в старом для клиентов и развиваем новые части. Клиенты используют часть старого + новый функционал, не замечая разницы. Мы сокращаем число долгов, убивая старое...<br>Наверное, как раз под прошлое подпадает, что он сам - это долг. Но прикол в том, что работает-то намного лучше, потому что без &quot;принципов проектирования&quot; созданный, работает, там нечему ломаться.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="8176250518626007878">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/8176250518626007878">Удалить</a></span></span></div><div class="comment-replies"><div id="c8176250518626007878-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c8176250518626007878-ra" class="thread-chrome thread-expanded"><div></div><div id="c8176250518626007878-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="8176250518626007878">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c8176250518626007878-ce"></div></li><li class="comment" id="c2805898968820649335"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Леонид Юрьев</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1359849245351#c2805898968820649335">3 февраля 2013&#8239;г. в 05:54</a></span></div><p class="comment-content">Для инвесторов  я сформулировал заклинание &quot;Отсутствие внутреннего качества исходного кода (технический долг) - это мера потерь инвестиций в долгосрочный софтверный проект&quot;. С приложением ссылки на этот пост дает эффект ;-)</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="2805898968820649335">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/2805898968820649335">Удалить</a></span></span></div><div class="comment-replies"><div id="c2805898968820649335-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c2805898968820649335-ra" class="thread-chrome thread-expanded"><div></div><div id="c2805898968820649335-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="2805898968820649335">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c2805898968820649335-ce"></div></li><li class="comment" id="c5512687343585157749"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Леонид Юрьев</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1359849586913#c5512687343585157749">3 февраля 2013&#8239;г. в 05:59</a></span></div><p class="comment-content">Короткие посты по теме https://plus.google.com/u/0/114590540937311233959/posts/iMDtR5wxR8V, https://plus.google.com/u/0/114590540937311233959/posts/PwE1oygYBqa, https://plus.google.com/u/0/114590540937311233959/posts/7Eg76KXqmUi</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="5512687343585157749">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/5512687343585157749">Удалить</a></span></span></div><div class="comment-replies"><div id="c5512687343585157749-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c5512687343585157749-ra" class="thread-chrome thread-expanded"><div></div><div id="c5512687343585157749-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="5512687343585157749">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c5512687343585157749-ce"></div></li><li class="comment" id="c4374279920408424364"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="http://www.byndyu.ru/" rel="nofollow">Alexander Byndyu</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1391101181685#c4374279920408424364">30 января 2014&#8239;г. в 22:59</a></span></div><p class="comment-content">Леонид, а как инвесторы на это реагируют? Они ведь вряд ли могут оценить качество кода. Для них это не абстракция?</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="4374279920408424364">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/4374279920408424364">Удалить</a></span></span></div><div class="comment-replies"><div id="c4374279920408424364-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c4374279920408424364-ra" class="thread-chrome thread-expanded"><div></div><div id="c4374279920408424364-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="4374279920408424364">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c4374279920408424364-ce"></div></li><li class="comment" id="c6338676955009877998"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Anton</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1397279369297#c6338676955009877998">12 апреля 2014&#8239;г. в 11:09</a></span></div><p class="comment-content">А откуда картинки с такой занимательной статистикой? В самом деле, сложно поверить, что кто-то научился так скурпулезно считать стоимость технических долгов.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="6338676955009877998">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/6338676955009877998">Удалить</a></span></span></div><div class="comment-replies"><div id="c6338676955009877998-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c6338676955009877998-ra" class="thread-chrome thread-expanded"><div></div><div id="c6338676955009877998-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="6338676955009877998">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c6338676955009877998-ce"></div></li><li class="comment" id="c5040989449884179435"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="http://www.byndyu.ru/" rel="nofollow">Alexander Byndyu</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1397460290030#c5040989449884179435">14 апреля 2014&#8239;г. в 13:24</a></span></div><p class="comment-content">Антон, на картинках написаны примерные цифры, но методика оценки тех. долга не сложная.<br>Нужно мониторить задачи, которые явÐ
1654»ÑÑŽÑ‚ся тех. долгом оценивать их по объему работы и отсюда брать конечную стоимость.<br>Да, она будет примерная, но обычно достаточно узнать порядок цифр, чтобы принимать решение о рефакторинге.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="5040989449884179435">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/5040989449884179435">Удалить</a></span></span></div><div class="comment-replies"><div id="c5040989449884179435-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c5040989449884179435-ra" class="thread-chrome thread-expanded"><div></div><div id="c5040989449884179435-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="5040989449884179435">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c5040989449884179435-ce"></div></li><li class="comment" id="c3389838053819233914"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user">Савелий</cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1436781189038#c3389838053819233914">13 июля 2015&#8239;г. в 14:53</a></span></div><p class="comment-content">Спасибо, очень познавательно! Вероятно, вы не заметили опечатку, скачок следует написать через букву О, а не Ё</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="3389838053819233914">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/3389838053819233914">Удалить</a></span></span></div><div class="comment-replies"><div id="c3389838053819233914-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c3389838053819233914-ra" class="thread-chrome thread-expanded"><div></div><div id="c3389838053819233914-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="3389838053819233914">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c3389838053819233914-ce"></div></li><li class="comment" id="c4859550384326478040"><div class="avatar-image-container"><img src="//resources.blogblog.com/img/blank.gif" alt=""/></div><div class="comment-block"><div class="comment-header"><cite class="user"><a href="http://www.byndyu.ru/" rel="nofollow">Alexander Byndyu</a></cite><span class="icon user "></span><span class="datetime secondary-text"><a rel="nofollow" href="https://blog.byndyu.ru/2008/12/blog-post.html?showComment=1436796699076#c4859550384326478040">13 июля 2015&#8239;г. в 19:11</a></span></div><p class="comment-content">Рад, что вам понравилось. Да, это опечатка, поправил.</p><span class="comment-actions secondary-text"><a class="comment-reply" target="_self" data-comment-id="4859550384326478040">Ответить</a><span class="item-control blog-admin blog-admin pid-476298591"><a target="_self" href="https://www.blogger.com/comment/delete/458002489272917533/4859550384326478040">Удалить</a></span></span></div><div class="comment-replies"><div id="c4859550384326478040-rt" class="comment-thread inline-thread hidden"><span class="thread-toggle thread-expanded"><span class="thread-arrow"></span><span class="thread-count"><a target="_self">Ответы</a></span></span><ol id="c4859550384326478040-ra" class="thread-chrome thread-expanded"><div></div><div id="c4859550384326478040-continue" class="continue"><a class="comment-reply" target="_self" data-comment-id="4859550384326478040">Ответить</a></div></ol></div></div><div class="comment-replybox-single" id="c4859550384326478040-ce"></div></li></ol><div id="top-continue" class="continue"><a class="comment-reply" target="_self">Добавить комментарий</a></div><div class="comment-replybox-thread" id="top-ce"></div><div class="loadmore hidden" data-post-id="2002061643571794461"><a target="_self">Ещё</a></div></div>
1655</div>
1656</div>
1657<p class='comment-footer'>
1658<div class='comment-form'>
1659<a name='comment-form'></a>
1660<p>
1661</p>
1662<a href='https://www.blogger.com/comment/frame/458002489272917533?po=2002061643571794461&hl=ru&saa=85391&origin=https://blog.byndyu.ru' id='comment-editor-src'></a>
1663<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' frameborder='0' height='410px' id='comment-editor' name='comment-editor' src='' width='100%'></iframe>
1664<script src='https://www.blogger.com/static/v1/jsbin/3790099508-comment_from_post_iframe.js' type='text/javascript'></script>
vendor: 1 bytes, line 1664
1664
1665<script type='text/javascript'>
1666      BLOG_CMT_createIframe('https://www.blogger.com/rpc_relay.html');
1667    </script>
1667
1668</div>
1669</p>
1670<div id='backlinks-container'>
1671<div id='Blog1_backlinks-container'>
1672</div>
1673</div>
1674</div>
1675</div>
1676
1677        </div></div>
1678      
1679</div>
1680<div class='blog-pager' id='blog-pager'>
1681<a class='home-link' href='https://blog.byndyu.ru/'>Главная страница</a>
1682<span id='blog-pager-older-link'>
1683<a class='blog-pager-older-link' href='https://blog.byndyu.ru/2008/11/blog-post.html' id='Blog1_blog-pager-older-link' title='Предыдущее'>&#8592; Предыдущее</a>
1684</span>
1685<span id='blog-pager-newer-link'>
1686<a class='blog-pager-newer-link' href='https://blog.byndyu.ru/2008/12/test-first-development.html' id='Blog1_blog-pager-newer-link' title='Следующее'>Следующее &#8594;</a>
1687</span>
1688</div>
1689<div class='clear'></div>
1690<div class='post-feeds' style='display:none;'>
1691<div class='feed-links'>
1692Подписаться на:
1693<a class='feed-link' href='https://blog.byndyu.ru/feeds/2002061643571794461/comments/default' target='_blank' type='application/atom+xml'>Комментарии к сообщению (Atom)</a>
1694</div>
1695</div>
1696</div></div>
1697</div>
1698</div>
1699<div class='column-left-outer'>
1700<div class='column-left-inner'>
1701<aside>
1702<div class='sidebar section' id='sidebar-left-1'><div class='widget HTML' data-version='1' id='HTML2'>
1703<div class='widget-content'>
1704</div>
1705<div class='clear'></div>
1706</div><div class='widget Header' data-version='1' id='Header1'>
1707<div id='header-inner'>
1708<div class='titlewrapper'>
1709<h1 class='title'>
1710<a href='https://blog.byndyu.ru/'>
1711Блог Александра Бындю
1712</a>
1713</h1>
1714</div>
1715<div class='descriptionwrapper'>
1716<p class='description'><span>Практикую теории</span></p>
1717</div>
1718</div>
1719</div><div class='widget HTML' data-version='1' id='HTML5'>
1720<div class='widget-content'>
1721<!--
1722  Мини-курс по Карте гипотез: продающие блоки для blog.byndyu.ru
1723
1724  Установка:
1725  1. Blogger -> Дизайн -> Добавить гаджет -> HTML/JavaScript.
1726  2. Вставить содержимое этого файла целиком и сохранить.
1727  3. Гаджет можно разместить в любом месте: сам он будет скрыт, а блоки
1728     автоматически попадут в сайдбар, ленту или статью.
1729
1730  Что можно менять: COURSE_PROMO_CONFIG в начале скрипта.
1731-->
1732
1733<style>
1734  :root {
1735    --course-promo-bg: #04050d;
1736    --course-promo-bg-soft: #0d1220;
1737    --course-promo-lime: #c8ff01;
1738    --course-promo-white: #f7f8fb;
1739    --course-promo-muted: #aeb5c5;
1740    --course-promo-line: rgba(255, 255, 255, 0.14);
1741    --course-promo-radius: 14px;
1742  }
1743
1744  .course-promo-controller {
1745    display: none !important;
1746  }
1747
1748  .course-promo {
1749    position: relative;
1750    box-sizing: border-box;
1751    overflow: hidden;
1752    color: var(--course-promo-white) !important;
1753    background:
1754      radial-gradient(circle at 92% 12%, rgba(54, 127, 230, 0.26), transparent 34%),
1755      radial-gradient(circle at 74% 88%, rgba(200, 255, 1, 0.10), transparent 34%),
1756      var(--course-promo-bg);
1757    border: 1px solid rgba(200, 255, 1, 0.32);
1758    border-radius: var(--course-promo-radius);
1759    box-shadow:
1760      0 18px 46px rgba(4, 5, 13, 0.2),
1761      0 0 0 4px rgba(200, 255, 1, 0.06);
1762    font-family: "Source Sans Pro", sans-serif;
1763  }
1764
1765  .course-promo::after {
1766    position: absolute;
1767    right: -40px;
1768    bottom: -58px;
1769    width: 190px;
1770    height: 190px;
1771    opacity: 0.4;
1772    background-image:
1773      radial-gradient(circle, #fff 0 3px, transparent 4px),
1774      linear-gradient(32deg, transparent 48%, rgba(255, 255, 255, 0.16) 49% 51%, transparent 52%);
1775    background-size: 38px 38px, 100% 100%;
1776    content: "";
1777    pointer-events: none;
1778  }
1779
1780  .course-promo__content {
1781    position: relative;
1782    z-index: 1;
1783  }
1784
1785  .course-promo__eyebrow {
1786    display: inline-flex;
1787    align-items: center;
1788    gap: 8px;
1789    margin: 0 0 12px;
1790    color: var(--course-promo-lime) !important;
1791    font-size: 12px;
1792    font-weight: 700;
1793    line-height: 1.2;
1794    letter-spacing: 0.1em;
1795    text-transform: uppercase;
1796  }
1797
1798  .course-promo__eyebrow::before {
1799    width: 7px;
1800    height: 7px;
1801    background: var(--course-promo-lime);
1802    border-radius: 50%;
1803    box-shadow: 0 0 0 5px rgba(200, 255, 1, 0.12);
1804    content: "";
1805  }
1806
1807  .course-promo .course-promo__title {
1808    margin: 0 0 12px !important;
1809    padding: 0 !important;
1810    color: var(--course-promo-white) !important;
1811    font-size: 30px;
1812    font-weight: 700 !important;
1813    line-height: 1.08;
1814    letter-spacing: -0.02em;
1815    text-transform: none !important;
1816  }
1817
1818  .course-promo__text {
1819    max-width: 650px;
1820    margin: 0 0 18px !important;
1821    color: #dce1ec !important;
1822    font-size: 17px;
1823    line-height: 1.5;
1824  }
1825
1826  .course-promo__facts {
1827    display: flex;
1828    flex-wrap: wrap;
1829    gap: 8px 16px;
1830    margin: 0 0 20px;
1831    padding: 0 !important;
1832    color: var(--course-promo-muted);
1833    font-size: 14px;
1834    line-height: 1.35;
1835    list-style: none !important;
1836    list-style-image: none !important;
1837    list-style-type: none !important;
1838  }
1839
1840  .course-promo__facts li,
1841  .widget .post-body .course-promo__facts li {
1842    position: relative;
1843    margin: 0 !important;
1844    padding-left: 14px;
1845    border: 0 !important;
1846  }
1847
1848  .course-promo__facts li::before,
1849  .widget .post-body .course-promo__facts li::before {
1850    position: absolute;
1851    top: 0.52em;
1852    left: 0;
1853    width: 5px;
1854    height: 5px;
1855    margin: 0;
1856    background: var(--course-promo-lime);
1857    border-radius: 50%;
1858    content: "" !important;
1859  }
1860
1861  .course-promo__facts li::marker {
1862    content: "" !important;
1863  }
1864
1865  .course-promo__actions {
1866    display: flex;
1867    flex-wrap: wrap;
1868    align-items: center;
1869    gap: 12px 18px;
1870  }
1871
1872  .course-promo .course-promo__button,
1873  .post-body .course-promo .course-promo__button {
1874    display: inline-flex;
1875    align-items: center;
1876    justify-content: center;
1877    box-sizing: border-box;
1878    min-height: 48px;
1879    padding: 12px 18px;
1880    color: var(--course-promo-bg) !important;
1881    background: var(--course-promo-lime);
1882    border: 0 !important;
1883    border-radius: 8px;
1884    font-size: 16px;
1885    font-weight: 700;
1886    line-height: 1.2;
1887    text-align: center;
1888    text-decoration: none !important;
1889    transition: transform 150ms ease, box-shadow 150ms ease, background 150ms ease;
1890  }
1891
1892  .course-promo .course-promo__button:hover,
1893  .post-body .course-promo .course-promo__button:hover {
1894    color: var(--course-promo-bg) !important;
1895    background: #d6ff3d;
1896    border: 0 !important;
1897    box-shadow: 0 8px 24px rgba(200, 255, 1, 0.18);
1898    transform: translateY(-1px);
1899  }
1900
1901  .course-promo .course-promo__button:focus-visible {
1902    outline: 3px solid rgba(200, 255, 1, 0.5);
1903    outline-offset: 4px;
1904  }
1905
1906  .course-promo__price {
1907    color: var(--course-promo-white);
1908    font-size: 20px;
1909    font-weight: 700;
1910    white-space: nowrap;
1911  }
1912
1913  .course-promo__price small {
1914    display: block;
1915    margin-top: 2px;
1916    color: var(--course-promo-muted);
1917    font-size: 12px;
1918    font-weight: 400;
1919  }
1920
1921  /* Вместо старого блока &#171;Диагностика ситуации&#8230;&#187; под статьями. */
1922  #HTML6 {
1923    display: none !important;
1924  }
1925
1926  /* Blogger прячет всю строку футера вместе с кнопкой &#171;Читать дальше&#187;. */
1927  .post-footer-line-1 {
1928    display: contents !important;
1929  }
1930
1931  .post-footer-line-1 > .post-timestamp1,
1932  .post-footer-line-1 > .post-labels {
1933    display: none !important;
1934  }
1935
1936  .post-footer-line-1 > .jump-link {
1937    display: block !important;
1938    margin: 24px 0 28px !important;
1939  }
1940
1941  .post-footer-line-1 > .jump-link > a {
1942    box-sizing: border-box;
1943    width: max-content;
1944    min-height: 42px;
1945    padding: 10px 16px;
1946    background: #fff;
1947    border: 1px solid #b83d25 !important;
1948    border-radius: 10px;
1949    box-shadow: 0 5px 16px rgba(184, 61, 37, 0.1);
1950    font-size: 16px;
1951    font-weight: 600;
1952    line-height: 1.2;
1953    transition: color 150ms ease, background 150ms ease, box-shadow 150ms ease, transform 150ms ease;
1954  }
1955
1956  .post-footer-line-1 > .jump-link > a:hover {
1957    color: #fff !important;
1958    background: #b83d25 !important;
1959    border-color: #b83d25 !important;
1960    box-shadow: 0 8px 22px rgba(184, 61, 37, 0.2);
1961    transform: translateY(-1px);
1962  }
1963
1964  /* Desktop: карточка в фиксированном сайдбаре. */
1965  .course-promo--sidebar {
1966    margin: 10px 0 24px;
1967    padding: 22px 20px;
1968    border-radius: 12px;
1969    box-shadow: none;
1970  }
1971
1972  .course-promo--sidebar::after {
1973    right: -72px;
1974    bottom: -78px;
1975  }
1976
1977  .course-promo--sidebar .course-promo__title {
1978    font-size: 25px;
1979  }
1980
1981  .course-promo--sidebar .course-promo__text {
1982    margin-bottom: 15px !important;
1983    font-size: 15px;
1984  }
1985
1986  .course-promo--sidebar .course-promo__facts {
1987    display: block;
1988    margin-bottom: 17px;
1989    font-size: 13px;
1990  }
1991
1992  .course-promo--sidebar .course-promo__facts li + li {
1993    margin-top: 6px !important;
1994  }
1995
1996  .course-promo--sidebar .course-promo__actions {
1997    display: block;
1998  }
1999
2000  .course-promo--sidebar .course-promo__button {
2001    width: 100%;
2002  }
2003
2004  .course-promo--sidebar .course-promo__price {
2005    display: block;
2006    margin-top: 11px;
2007    font-size: 17px;
2008    text-align: center;
2009  }
2010
2011  /* Лента и конец статьи. */
2012  .course-promo--feed,
2013  .course-promo--end {
2014    width: 100%;
2015    max-width: 800px;
2016    margin-right: auto;
2017    margin-left: auto;
2018    padding: 30px 32px;
2019  }
2020
2021  .course-promo--feed {
2022    margin-top: 4px;
2023    margin-bottom: 56px;
2024  }
2025
2026  .course-promo--end {
2027    margin-top: 50px;
2028    margin-bottom: 8px;
2029  }
2030
2031  .course-promo--end .course-promo__title {
2032    max-width: 620px;
2033  }
2034
2035  /* Mobile: короткая панель после вовлечения в чтение. */
2036  .course-promo-mobile {
2037    position: fixed;
2038    right: 10px;
2039    bottom: calc(var(--course-promo-mobile-offset, 10px) + env(safe-area-inset-bottom));
2040    left: 10px;
2041    z-index: 2147482000;
2042    display: none;
2043    align-items: center;
2044    gap: 12px;
2045    box-sizing: border-box;
2046    min-height: 64px;
2047    padding: 10px 48px 10px 14px;
2048    color: var(--course-promo-white);
2049    background: rgba(4, 5, 13, 0.97);
2050    border: 1px solid var(--course-promo-line);
2051    border-radius: 13px;
2052    box-shadow: 0 16px 44px rgba(0, 0, 0, 0.34);
2053    opacity: 0;
2054    transform: translateY(18px);
2055    transition: opacity 180ms ease, transform 180ms ease;
2056    -webkit-backdrop-filter: blur(14px);
2057    backdrop-filter: blur(14px);
2058  }
2059
2060  .course-promo-mobile.is-visible {
2061    opacity: 1;
2062    transform: translateY(0);
2063  }
2064
2065  .course-promo-mobile__copy {
2066    min-width: 0;
2067    flex: 1;
2068  }
2069
2070  .course-promo-mobile__copy strong {
2071    display: block;
2072    overflow: hidden;
2073    color: #fff;
2074    font-size: 14px;
2075    line-height: 1.15;
2076    text-overflow: ellipsis;
2077    white-space: nowrap;
2078  }
2079
2080  .course-promo-mobile__copy span {
2081    display: block;
2082    margin-top: 3px;
2083    color: var(--course-promo-muted);
2084    font-size: 12px;
2085    line-height: 1.15;
2086  }
2087
2088  .course-promo-mobile .course-promo-mobile__button {
2089    flex: 0 0 auto;
2090    padding: 10px 13px;
2091    color: var(--course-promo-bg) !important;
2092    background: var(--course-promo-lime);
2093    border: 0 !important;
2094    border-radius: 7px;
2095    font-size: 13px;
2096    font-weight: 700;
2097    line-height: 1;
2098    text-decoration: none !important;
2099  }
2100
2101  .course-promo-mobile__close {
2102    position: absolute;
2103    top: 50%;
2104    right: 2px;
2105    width: 42px;
2106    height: 42px;
2107    padding: 0;
2108    color: #c4cad6;
2109    background: transparent;
2110    border: 0;
2111    font: 24px/1 Arial, sans-serif;
2112    cursor: pointer;
2113    transform: translateY(-50%);
2114  }
2115
2116  @media only screen and (max-width: 960px) {
2117    .post-footer-line-1 > .jump-link > a {
2118      width: 100%;
2119      justify-content: center;
2120    }
2121
2122    .course-promo--sidebar {
2123      display: none;
2124    }
2125
2126    .course-promo--feed,
2127    .course-promo--end {
2128      width: auto;
2129      margin-right: 0;
2130      margin-left: 0;
2131      padding: 24px 20px;
2132      border-radius: 12px;
2133    }
2134
2135    .course-promo--feed {
2136      margin-bottom: 44px;
2137    }
2138
2139    .course-promo--end {
2140      margin-top: 40px;
2141    }
2142
2143    .course-promo .course-promo__title {
2144      font-size: 26px;
2145    }
2146
2147    .course-promo__text {
2148      font-size: 16px;
2149    }
2150
2151    .course-promo__facts {
2152      display: block;
2153    }
2154
2155    .course-promo__facts li + li {
2156      margin-top: 6px !important;
2157    }
2158
2159    .course-promo__actions {
2160      align-items: stretch;
2161      flex-direction: column;
2162    }
2163
2164    .course-promo__button {
2165      width: 100%;
2166    }
2167
2168    .course-promo__price {
2169      font-size: 17px;
2170      text-align: center;
2171    }
2172
2173    .course-promo-mobile {
2174      display: flex;
2175    }
2176  }
2177
2178  @media only screen and (max-width: 390px) {
2179    .course-promo-mobile__copy span {
2180      display: none;
2181    }
2182  }
2183
2184  @media (prefers-reduced-motion: reduce) {
2185    .course-promo,
2186    .course-promo-mobile,
2187    .course-promo__button {
2188      transition: none !important;
2189    }
2190  }
2191
2192  @media print {
2193    .course-promo,
2194    .course-promo-mobile {
2195      display: none !important;
2196    }
2197  }
2198</style>
2199
2200<script>
2201  (function () {
2202    "use strict";
2203
2204    var scriptElement = document.currentScript;
2205    var embeddedStyle = scriptElement && scriptElement.previousElementSibling;
2206    if (embeddedStyle && embeddedStyle.tagName === "STYLE") {
2207      var existingStyle = document.getElementById("course-promo-styles");
2208      if (existingStyle) {
2209        embeddedStyle.remove();
2210      } else {
2211        embeddedStyle.id = "course-promo-styles";
2212        document.head.appendChild(embeddedStyle);
2213      }
2214    }
2215
2216    var controller = scriptElement && scriptElement.closest(".widget");
2217    if (controller) controller.classList.add("course-promo-controller");
2218
2219    var COURSE_PROMO_CONFIG = {
2220      url: "https://xn--80aajikek0bigwf.xn--p1ai/productminicourse",
2221      price: "10 000 &#8381;",
2222      campaign: "hypothesis_map_minicourse",
2223      variants: {
2224        A: {
2225          title: "Соберите стратегию, которой можно управлять",
2226          shortTitle: "Мини-курс по Карте гипотез"
2227        },
2228        B: {
2229          title: "Перестаньте выбирать идеи на интуиции",
2230          shortTitle: "Превратите идеи в стратегию"
2231        }
2232      }
2233    };
2234
2235    function onReady(callback) {
2236      if (document.readyState === "loading") {
2237        document.addEventListener("DOMContentLoaded", callback, { once: true });
2238      } else {
2239        callback();
2240      }
2241    }
2242
2243    function getVariant() {
2244      var storageKey = "byndyuCoursePromoVariant";
2245      try {
2246        var saved = localStorage.getItem(storageKey);
2247        if (saved === "A" || saved === "B") return saved;
2248        var selected = Math.random() < 0.5 ? "A" : "B";
2249        localStorage.setItem(storageKey, selected);
2250        return selected;
2251      } catch (error) {
2252        return "A";
2253      }
2254    }
2255
2256    function buildUrl(placement, variant) {
2257      var url = new URL(COURSE_PROMO_CONFIG.url);
2258      url.searchParams.set("utm_source", "blog_byndyu_ru");
2259      url.searchParams.set("utm_medium", "owned_content");
2260      url.searchParams.set("utm_campaign", COURSE_PROMO_CONFIG.campaign);
2261      url.searchParams.set("utm_content", placement);
2262      url.searchParams.set("utm_term", variant);
2263      return url.toString();
2264    }
2265
2266    function createCard(modifier, placement, copy, variant) {
2267      var section = document.createElement(modifier === "sidebar" ? "aside" : "section");
2268      section.className = "course-promo course-promo--" + modifier;
2269      section.setAttribute("aria-label", "Мини-курс по Карте гипотез");
2270      section.setAttribute("data-course-promo-placement", placement);
2271      section.setAttribute("data-course-promo-variant", variant);
2272      section.innerHTML =
2273        '<div class="course-promo__content">' +
2274          '<div class="course-promo__eyebrow">8 коротких видеоуроков</div>' +
2275          '<h2 class="course-promo__title">' + copy.title + '</h2>' +
2276          '<p class="course-promo__text">Постройте Карту гипотез на своей реальной ситуации и превратите цели, идеи и риски в понятную систему решений.</p>' +
2277          '<ul class="course-promo__facts" aria-label="Что входит в курс">' +
2278            '<li>Шаблоны и практические задания</li>' +
2279            '<li>Живые разборы с куратором</li>' +
2280            '<li>Общий чат и доступ навсегда</li>' +
2281          '</ul>' +
2282          '<div class="course-promo__actions">' +
2283            '<a class="course-promo__button" data-course-cta="' + placement + '" href="' + buildUrl(placement, variant) + '">Посмотреть программу&nbsp;&#8594;</a>' +
2284            '<span class="course-promo__price">' + COURSE_PROMO_CONFIG.price + '<small>за весь курс &#183; онлайн</small></span>' +
2285          '</div>' +
2286        '</div>';
2287      return section;
2288    }
2289
2290    function isArticlePage(postBodies) {
2291      return /^\/\d{4}\/\d{2}\//.test(location.pathname) && postBodies.length === 1;
2292    }
2293
2294    function installSidebar(copy, variant) {
2295      var host = document.querySelector("#HTML5 .widget-content");
2296      if (host) {
2297        host.replaceChildren(createCard("sidebar", "sidebar", copy, variant));
2298        if (controller && controller.contains(host)) {
2299          controller.classList.remove("course-promo-controller");
2300        }
2301        return;
2302      }
2303
2304      var sidebar = document.querySelector("#sidebar-left-1");
2305      if (sidebar) sidebar.appendChild(createCard("sidebar", "sidebar", copy, variant));
2306    }
2307
2308    function installArticlePromos(postBody, copy, variant) {
2309      var endCopy = {
2310        title: "Хотите применить этот подход к своей ситуации?"
2311      };
2312      postBody.appendChild(createCard("end", "article_end", endCopy, variant));
2313    }
2314
2315    function installFeedPromo(copy, variant) {
2316      var firstPost = document.querySelector(".blog-posts .post-outer");
2317      if (!firstPost || !firstPost.parentNode) return;
2318      firstPost.insertAdjacentElement("afterend", createCard("feed", "feed_after_first", copy, variant));
2319    }
2320
2321    function installMobileBar(copy, variant) {
2322      var placement = "mobile_bar";
2323      var bar = document.createElement("aside");
2324      bar.className = "course-promo-mobile";
2325      bar.setAttribute("aria-label", "Мини-курс по Карте гипотез");
2326      bar.innerHTML =
2327        '<div class="course-promo-mobile__copy">' +
2328          '<strong>' + copy.shortTitle + '</strong>' +
2329          '<span>8 уроков &#183; ' + COURSE_PROMO_CONFIG.price + '</span>' +
2330        '</div>' +
2331        '<a class="course-promo-mobile__button" data-course-cta="' + placement + '" href="' + buildUrl(placement, variant) + '">Подробнее</a>' +
2332        '<button class="course-promo-mobile__close" type="button" aria-label="Закрыть предложение">&#215;</button>';
2333
2334      var closed = false;
2335      try { closed = sessionStorage.getItem("byndyuCoursePromoClosed") === "1"; } catch (error) {}
2336      if (closed) return;
2337
2338      document.body.appendChild(bar);
2339
2340      var endCard = document.querySelector(".course-promo--end");
2341      var endCardVisible = false;
2342      var engagedByTime = false;
2343      if (endCard && "IntersectionObserver" in window) {
2344        new IntersectionObserver(function (entries) {
2345          endCardVisible = entries[0] && entries[0].isIntersecting;
2346          updateVisibility();
2347        }, { threshold: 0.15 }).observe(endCard);
2348      }
2349
2350      function updateCookieOffset() {
2351        var notice = document.querySelector("#cookieChoiceInfo");
2352        var offset = 10;
2353        if (notice && getComputedStyle(notice).display !== "none" && notice.offsetHeight > 0) {
2354          var noticeRect = notice.getBoundingClientRect();
2355          if (noticeRect.bottom > innerHeight - 16) {
2356            offset = Math.ceil(innerHeight - noticeRect.top + 10);
2357          }
2358        }
2359        bar.style.setProperty("--course-promo-mobile-offset", offset + "px");
2360      }
2361
2362      function updateVisibility() {
2363        updateCookieOffset();
2364        var shouldShow = innerWidth <= 960 && (scrollY >= 180 || engagedByTime) && !endCardVisible;
2365        bar.classList.toggle("is-visible", shouldShow);
2366      }
2367
2368      var delayedShow = window.setTimeout(function () {
2369        engagedByTime = true;
2370        updateVisibility();
2371      }, 4500);
2372      window.addEventListener("scroll", updateVisibility, { passive: true });
2373      window.addEventListener("resize", updateVisibility);
2374
2375      bar.querySelector(".course-promo-mobile__close").addEventListener("click", function () {
2376        window.clearTimeout(delayedShow);
2377        try { sessionStorage.setItem("byndyuCoursePromoClosed", "1"); } catch (error) {}
2378        bar.remove();
2379      });
2380    }
2381
2382    function installTracking() {
2383      document.addEventListener("click", function (event) {
2384        var link = event.target.closest("[data-course-cta]");
2385        if (!link) return;
2386
2387        var placement = link.getAttribute("data-course-cta");
2388        var variant = document.documentElement.getAttribute("data-course-promo-variant") || "A";
2389        var payload = {
2390          course_name: "Мини-курс по Карте гипотез",
2391          cta_placement: placement,
2392          cta_variant: variant,
2393          article_path: location.pathname
2394        };
2395
2396        if (typeof window.gtag === "function") {
2397          window.gtag("event", "course_cta_click", payload);
2398        } else {
2399          window.dataLayer = window.dataLayer || [];
2400          window.dataLayer.push(Object.assign({ event: "course_cta_click" }, payload));
2401        }
2402      });
2403    }
2404
2405    onReady(function () {
2406      if (document.documentElement.hasAttribute("data-course-promo-ready")) return;
2407      document.documentElement.setAttribute("data-course-promo-ready", "");
2408
2409      var variant = getVariant();
2410      var copy = COURSE_PROMO_CONFIG.variants[variant];
2411      var postBodies = Array.prototype.slice.call(document.querySelectorAll(".post-body.entry-content"));
2412      document.documentElement.setAttribute("data-course-promo-variant", variant);
2413
2414      installSidebar(copy, variant);
2415
2416      if (isArticlePage(postBodies)) {
2417        installArticlePromos(postBodies[0], copy, variant);
2418      } else {
2419        installFeedPromo(copy, variant);
2420      }
2421
2422      installMobileBar(copy, variant);
2423      installTracking();
2424    });
2425  }());
2426</script>
2426
2427</div>
2428<div class='clear'></div>
2429</div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'>
2430<h2>Популярные статьи</h2>
2431<div class='widget-content popular-posts'>
2432<ul>
2433<li>
2434<a href='https://blog.byndyu.ru/2009/12/blog-post.html'>Принцип инверсии зависимости</a>
2435</li>
2436<li>
2437<a href='https://blog.byndyu.ru/2010/06/domain-driven-design-aggregation-root.html'>Domain-Driven Design: aggregation root</a>
2438</li>
2439<li>
2440<a href='https://blog.byndyu.ru/2009/10/blog-post.html'>Принцип единственности ответственности</a>
2441</li>
2442<li>
2443<a href='https://blog.byndyu.ru/2011/12/domain-driven-design.html'>Domain-Driven Design: Простые способы улучшить дизайн ПО</a>
2444</li>
2445<li>
2446<a href='https://blog.byndyu.ru/2011/01/domain-driven-design-repository.html'>Domain-Driven Design: Repository</a>
2447</li>
2448<li>
2449<a href='https://blog.byndyu.ru/2011/08/repository.html'>Проблемный шаблон Repository</a>
2450</li>
2451<li>
2452<a href='https://blog.byndyu.ru/2026/08/blog-post_705.html'>Операционный директор между бюджетом и хаосом: одно ведро воды на двадцать грядок</a>
2453</li>
2454<li>
2455<a href='https://blog.byndyu.ru/2009/10/blog-post_14.html'>Принцип открытости/закрытости</a>
2456</li>
2457<li>
2458<a href='https://blog.byndyu.ru/2010/05/domain-driven-design.html'>Domain-Driven Design: создание домена</a>
2459</li>
2460<li>
2461<a href='https://blog.byndyu.ru/2009/10/blog-post_29.html'>Принцип замещения Лисков</a>
2462</li>
2463</ul>
2464<div class='clear'></div>
2465</div>
2466</div></div>
2467</aside>
2468</div>
2469</div>
2470<div class='column-right-outer'>
2471<div class='column-right-inner'>
2472<aside>
2473</aside>
2474</div>
2475</div>
2476</div>
2477<div style='clear: both'></div>
2478<!-- columns -->
2479</div>
2480<!-- main -->
2481</div>
2482</div>
2483<div class='main-cap-bottom cap-bottom'>
2484<div class='cap-left'></div>
2485<div class='cap-right'></div>
2486</div>
2487</div>
2488<footer>
2489<!-- syntaxhighlighter -->
2490<link href='https://byndyu.ru/sh/shCore.css' rel='stylesheet'/>
2491<link href='https://byndyu.ru/sh/shThemeDefault.css' rel='stylesheet'/>
2492<script src='https://byndyu.ru/sh/shCore.js' type='text/javascript'></script>
vendor: 1 bytes, line 2492
2492
2493<script src='https://byndyu.ru/sh/shBrushCSharp.js' type='text/javascript'></script>
vendor: 1 bytes, line 2493
2493
2494<script src='https://byndyu.ru/sh/shBrushSql.js' type='text/javascript'></script>
vendor: 1 bytes, line 2494
2494
2495<script src='https://byndyu.ru/sh/shBrushXml.js' type='text/javascript'></script>
2495
2496<div class='footer-outer'>
2497<div class='footer-cap-top cap-top'>
2498<div class='cap-left'></div>
2499<div class='cap-right'></div>
2500</div>
2501<div class='fauxborder-left footer-fauxborder-left'>
2502<div class='fauxborder-right footer-fauxborder-right'></div>
2503<div class='region-inner footer-inner'>
2504<div class='foot no-items section' id='footer-1'></div>
2505<!-- outside of the include in order to lock Attribution widget -->
2506<div class='foot no-items section' id='footer-3'></div>
2507</div>
2508</div>
2509<div class='footer-cap-bottom cap-bottom'>
2510<div class='cap-left'></div>
2511<div class='cap-right'></div>
2512</div>
2513</div>
2514<script type='text/javascript'>
2515 SyntaxHighlighter.config.bloggerMode = true;
2516 SyntaxHighlighter.all();
2517</script>
2517
2518</footer>
2519<!-- content -->
2520</div>
2521</div>
2522<div class='content-cap-bottom cap-bottom'>
2523<div class='cap-left'></div>
2524<div class='cap-right'></div>
2525</div>
2526</div>
2527</div>
2528<script type='text/javascript'>
2529    window.setTimeout(function() {
2530        document.body.className = document.body.className.replace('loading', '');
2531      }, 10);
2532  </script>
2532
2533<!-- Go to www.addthis.com/dashboard to customize your tools -->
2534<script src='//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5187f1482504e318' type='text/javascript'></script>
2534
2535
2536<script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/851759228-widgets.js"></script>
vendor: 1 bytes, line 2536
2536
2537<script type='text/javascript'>
2538window['__wavt'] = 'AAPvtVlbxIBqpjOpYJRpZoLfA7x7:1790240364019';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d458002489272917533','//blog.byndyu.ru/2008/12/blog-post.html','458002489272917533');
2539_WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '458002489272917533', 'title': '\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e', 'url': 'https://blog.byndyu.ru/2008/12/blog-post.html', 'canonicalUrl': 'https://blog.byndyu.ru/2008/12/blog-post.html', 'homepageUrl': 'https://blog.byndyu.ru/', 'searchUrl': 'https://blog.byndyu.ru/search', 'canonicalHomepageUrl': 'https://blog.byndyu.ru/', 'blogspotFaviconUrl': 'https://blog.byndyu.ru/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': '', 'encoding': 'UTF-8', 'locale': 'ru', 'localeUnderscoreDelimited': 'ru', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e - Atom\x22 href\x3d\x22https://blog.byndyu.ru/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e - RSS\x22 href\x3d\x22https://blog.byndyu.ru/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/458002489272917533/posts/default\x22 /\x3e\n\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e - Atom\x22 href\x3d\x22https://blog.byndyu.ru/feeds/2002061643571794461/comments/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/7ce469edaf870342', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': '\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443', 'key': 'link', 'shareMessage': '\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': '\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0432 Facebook', 'target': 'facebook'}, {'name': '\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0431\u043b\u043e\u0433\u0435', 'key': 'blogThis', 'shareMessage': '\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0431\u043b\u043e\u0433\u0435', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': '\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0432 X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': '\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0432 Pinterest', 'target': 'pinterest'}, {'name': '\u042d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430', 'key': 'email', 'shareMessage': '\u042d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27ru\x27};\x3c/script\x3e'}
2539, 'hasCustomJumpLinkMessage': true, 'jumpLinkMessage': '\u0427\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435 \xbb', 'pageType': 'item', 'postId': '2002061643571794461', 'postImageThumbnailUrl': 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s72-c/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg', 'postImageUrl': 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s1600/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg', 'pageName': '\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u043e\u043b\u0433\u0438', 'pageTitle': '\u0411\u043b\u043e\u0433 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0411\u044b\u043d\u0434\u044e: \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u043e\u043b\u0433\u0438'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': '\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c', 'linkCopiedToClipboard': '\u0421\u0441\u044b\u043b\u043a\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430!', 'ok': '\u041e\u041a', 'postLink': '\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': '\u0421\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': '\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u043e\u043b\u0433\u0438', 'description': '\u042d\u0442\u043e\u0442 \u0442\u0435\u0440\u043c\u0438\u043d \u0432\u043f\u0435\u0440\u0432\u044b\u0435 \u0432\u0432\u0435\u043b Ward Cunningham :    \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u043e\u043b\u0433\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0442\u0443 \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0440\u0435\u0448\u0430\u0435\u043c (\u0445\u043e\u0440\u043e\u0448\u043e, \u0435\u0441\u043b\u0438 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e) \u043d\u0435 ...', 'featuredImage': 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhraoW9qbNZze5xgJQAM-c5VBpWpuhuWDRqP8aasrkC2b8MKhKJpbW2HLPXdrFeMl5FLt4b9ZLujZJjYyXVzSYEwRMtwQMexP2fDXgJj_WD_r4NPu6v7civBDKEs-rshvQMbA5yS5EyP4FlHS9QEwOH0hnr69UOgiswkETddcYhibFn62rmvmH_yWorKA/s1600/%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0%20%281%29.jpg', 'url': 'https://blog.byndyu.ru/2008/12/blog-post.html', 'type': 'item', 'isSingleItem': true, 'isMultipleItems': false, 'isError': false, 'isPage': false, 'isPost': true, 'isHomepage': false, 'isArchive': false, 'isLabelSearch': false, 'postId': 2002061643571794461}}]);
2540_WidgetManager._RegisterWidget('_PageListView', new _WidgetInfo('PageList2', 'crosscol', document.getElementById('PageList2'), {'title': '\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u044b', 'links': [{'isCurrentPage': false, 'href': 'https://blog.byndyu.ru/', 'title': '\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438'}, {'isCurrentPage': false, 'href': 'https://blog.byndyu.ru/p/blog-page_19.html', 'id': '8994562925443255105', 'title': 'IT-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430'}, {'isCurrentPage': false, 'href': 'https://blog.byndyu.ru/p/blog-page_4.html', 'id': '1423215697637586111', 'title': '\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435'}, {'isCurrentPage': false, 'href': 'https://blog.byndyu.ru/p/blog-page_95.html', 'id': '1931739866784042719', 'title': '\u0418\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u044b\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438'}, {'isCurrentPage': false, 'href': 'https://blog.byndyu.ru/p/blog-page_24.html', 'id': '6271735362188676636', 'title': '\u041e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043a\u0430\u0440\u044c\u0435\u0440\u0430'}], 'mobile': false, 'showPlaceholder': true, 'hasCurrentPage': false}
2540, 'displayModeFull'));
2541_WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML1', 'crosscol-overflow', document.getElementById('HTML1'), {}, 'displayModeFull'));
2542_WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/762570179-lbx__ru.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/828616780-lightbox_bundle.css'}, 'displayModeFull'));
2543_WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar-left-1', document.getElementById('HTML2'), {}, 'displayModeFull'));
2544_WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'sidebar-left-1', document.getElementById('Header1'), {}, 'displayModeFull'));
2545_WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML5', 'sidebar-left-1', document.getElementById('HTML5'), {}, 'displayModeFull'));
2546_WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-left-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull'));
2547</script>
2547
2548</body>
2549</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.