Когда я разделяю большие методы (или процедуры, или функции - этот вопрос не является специфическим для ООП, но, поскольку я работаю на языках ООП в 99% случаев, это терминология, которая мне наиболее удобна) на множество маленьких Я часто бываю недоволен результатами. Об этих маленьких методах становится сложнее рассуждать, чем когда они были просто блоками кода в большом, потому что, когда я их извлекаю, я теряю много базовых предположений, которые исходят из контекста вызывающей стороны.
Позже, когда я смотрю на этот код и вижу отдельные методы, я не сразу знаю, откуда они вызываются, и думаю о них как об обычных частных методах, которые можно вызывать из любого места в файле. Например, представьте, что метод инициализации (конструктор или другой) разделен на серию маленьких: в контексте самого метода вы четко знаете, что состояние объекта все еще недопустимо, но в обычном частном методе вы, вероятно, исходите из предположения, что объект уже инициализирован и находится в действительном состоянии.
Единственное решение, которое я видел для этого, - это where
предложение в Haskell, которое позволяет вам определять небольшие функции, которые используются только в «родительской» функции. В основном это выглядит так:
len x y = sqrt $ (sq x) + (sq y)
where sq a = a * a
Но другие языки, которые я использую, не имеют ничего подобного - самым близким является определение лямбды в локальной области, что, вероятно, еще более запутанно.
Итак, мой вопрос - вы сталкиваетесь с этим, и вы вообще видите, что это проблема? Если да, то как вы обычно решаете эту проблему, особенно в «основных» языках ООП, таких как Java / C # / C ++?
Редактировать дубликаты: как уже заметили другие, уже есть вопросы, обсуждающие методы расщепления, и небольшие вопросы, которые являются однострочными. Я читаю их, и они не обсуждают проблему базовых предположений, которые могут быть получены из контекста вызывающей стороны (в примере выше, объект инициализируется). В этом суть моего вопроса, и именно поэтому мой вопрос отличается.
Обновление: если вы следили за этим вопросом и обсуждением под ним, вам может понравиться эта статья Джона Кармака по этому вопросу , в частности:
Помимо понимания фактического выполняемого кода, встроенные функции также имеют то преимущество, что они не позволяют вызывать функцию из других мест. Это звучит смешно, но в этом есть смысл. По мере того, как кодовая база растет с годами, у вас будет много возможностей использовать ярлык и просто вызывать функцию, которая выполняет только ту работу, которую, по вашему мнению, необходимо выполнить. Может существовать функция FullUpdate (), которая вызывает PartialUpdateA () и PartialUpdateB (), но в некоторых случаях вы можете осознать (или подумать), что вам нужно всего лишь выполнить PartialUpdateB (), и вы эффективны, избегая других Работа. Много-много ошибок проистекает из этого. Большинство ошибок являются результатом того, что состояние выполнения не совсем то, что вы думаете.