Статьи

Разработка на основе комментариев

Вы, наверное, слышали о Test Driven Development , методологии программирования, которая фокусируется на тестовых примерах в качестве основы для проектирования и разработки кода. Возможно, вы также слышали о Behavior Driven Development , более целостном подходе, который фокусируется на поведении приложения до и во время процесса разработки.

Что ж, позвольте мне рассказать вам о моей методологии программирования — комментирование разработки . Начните с написания комментария на понятном языке, который объясняет, что должен делать фрагмент кода и почему. Затем напишите код.

Иногда это самый прямой способ решения проблемы; если это легко объяснить, но трудно выразить в логике, внутренний дискурс, который вы получаете, записав его таким образом, может помочь прояснить ваше мышление в направлении логического решения. И наоборот, иногда легко написать код, но гораздо сложнее его объяснить; в этом случае написание комментария может помочь вам уточнить назначение кода таким образом, чтобы сделать его понятным для других людей. Написание комментария похоже на предварительный курсор к документации.

И действительно, бывают моменты, когда я пишу комментарий, и обнаруживаю, что мое мышление по поводу рассматриваемого кода меняется. Потому что объяснение звучит смешно, или потому что я должен объяснить недостаток или нежелательный компромисс. Объяснение этого кому-то еще — что и должен делать хороший комментарий — помогает вам лучше понять его самостоятельно, а иногда это приводит к его полному изменению или отмене.

Когда я писал свой доступный скрипт перетаскивания, dbx , было несколько случаев, когда я просто не мог понять, что делать дальше — как выразить в логике поведение, которое выглядело и чувствовалось правильным. Поэтому я взялся за эту технику, начав с объяснения:

//if - the direction of movement is positive; and
//	clone left/top plus clone width/height is greater than box left/top; and
//	clone left/top is less than box left/top
//or - the direction of movement is negative; and
//	clone left/top is less than box left/top; and
//	clone left/top plus clone width/height is greater than box left/top

Как только я получил это, это был просто случай написания кода для реализации того, что я объяснил:

 if
(
	(this.positive
		&& cloneprops.xy + cloneprops.wh > boxprops.xy
		&& cloneprops.xy < boxprops.xy)
	||
	(!this.positive
		&& cloneprops.xy < boxprops.xy
		&& cloneprops.xy + cloneprops.wh > boxprops.xy)
)

И наоборот, были ситуации, когда я сразу знал, какой код писать, но я также знал, что быстро забуду, для чего он:

 var sibling = dbx.getSiblingBox(this.box, 'nextSibling');
if(this.box == sibling || this.boxes[i] == sibling) { return; }

Итак, в комментариях это прописано:

 //look for a next sibling of this box
//and don't continue if there isn't one,
//or it's the same as the box we're inserting before
//so that we're not doing an action that would result in no change
//this filtering improves efficiency generally,
//and is necessary specifically to stabilize the animation
//otherwise the multiple unecessary calls would overload the animation timers
//and the result would be snap movement with no apparent transition

Я понял, как тяжело возвращаться к сценарию за разом, только не зная, как он работает. Взгляните на этот пример, для сценария шахматного анализа, который я написал много лет назад:

 sqR=new Array(vmr,vmr);
for(j=0;j<sqid[vmr][1];j++){
	if(sqid[(vmr-1)]&&(sqid[vmr][1]-sqid[(vmr-1)][1]==1)){
		sqR[2]=vmr-1;
		com(vmn,sqR[2]);
		}
	if(sqid[(vmr-9)]&&(sqid[vmr][1]-sqid[(vmr-9)][1]==1&&sqid[vmr][0]-sqid[(vmr-9)][0]==1)){
		sqR[3]=vmr-9;
		com(vmn,sqR[3]);
		}
	}

Не спрашивайте меня, что он делает — я понятия не имею!

Так что теперь я комментирую, как будто это выходит из моды, по крайней мере, одна строка комментария для каждой строки кода, и обычно две или три. Иногда мои комментарии являются мини-эпопеями, как этот монстр:

 /*
use offleft positioning instead of display/visibility,
so that the menus are still accessible to screenreaders
the height and overflow:scroll is to reduce the amount of rendered output,
which speeds up the onload process
(using clip or overflow:hidden would also hide them from screenreaders)
but there are rendering or positioning problems
in mac/ie5, old gecko and opera < 7.5
in fact it screws up opera 7.23 completely - parts of the browser UI freeze up (!?)
so the styles are hidden from opera < 7.5 using the html[xmlns] selector
http://www.dithered.com/css_filters/css_only/xmlns_attribute_selector.html
this means that it won't happen on pages without an xmlns attribute
in other words - on HTML 4 pages, any browser-based screenreader using Opera 7.5-8 won't get the submenus
opera 9 and other browsers aren't affected because all are included in later selectors somewhere
opera's own speech/reading capabilities are not affected either,
because it generates events that open the menus, resetting all of this
and afaik there isn't any other browser-based reader that uses opera
so the likelihood is that this hole won't affect anybody at all
nonetheless it's still unfortunate, but it's practicably unavoidable -
the only other way to differentiate opera versions like this is the selector:lang(xx) pseudo-class,
but then we'd need a new custom varible to specify the user's language code
the styles are also hidden from old gecko builds using the commented selector hack
and from konqueror < 3.2 using the backslash hack, because it makes the navbar collapse
*/

Все из которых документируют одну строку CSS:

 html/**/[xmlns] .udm u\l{position:absolute;left:-10000px;height:0;overflow:scroll;}

Так что, ладно, все это немного не по зубам. Но никто никогда не будет жаловаться на тебя за то, что ты написал слишком много комментариев! Мои коллеги даже дополнили меня качеством и тщательностью моих комментариев. Может быть, это растягивает смысл называть это методологией, но это все еще хорошая идея.