Я согласен с ответом Леандро. Защитное программирование редко используется в языке Smalltalk. Нет ни статической типизации для принудительного выполнения чего-либо, ни личных сообщений. Smalltalk является открытым и поздним. Но с другой стороны, ошибки редко бывают катастрофическими (Smalltalk вообще не падает при ошибке).
Это позднее связывание вместе с корректным восстановлением после ошибок делает эволюцию системы очень легким процессом. Когда вы программируете на Smalltalk, вы ничего не делаете, кроме как заставляете живую систему развиваться, если вы думаете об этом.
Поскольку единственное, что у нас есть, — это отправлять сообщения, мы можем в конечном итоге использовать это для согласования контрактов или просто для проверки некоторых предварительных условий.
Стратегия, которую вы предлагаете, возможна благодаря использованию Exception. Идея состоит в том, что иногда лучше иметь раннее исключение, наиболее близкое к первопричине, чем позднее исключение, которое сложнее отлаживать и исправлять. Посмотрите, например, на сообщение #shouldNotImplement
и его отправителей: вы увидите, что иногда оно используется для предотвращения использования #new
.
Также не забывайте, что существует сообщение #initialize
, которое можно использовать для присвоения разумного значения по умолчанию переменным экземпляра (что-то вроде конструктора по умолчанию в C++). Есть варианты, когда вы хотите передать дополнительную информацию: для коллекций, которые обычно создаются через #new:
, есть сообщение #initialize:
, принимающее размер в качестве аргумента. Вы можете по желанию усовершенствовать подобные механизмы для передачи другой информации при создании.
Но не пытайтесь предотвратить использование #basicNew
. Вы причините себе боль, сломав некоторые службы, полагающиеся на эту низкоуровневую функцию, например, изменяя существующие экземпляры при изменении макета класса, например, копируя, сохраняя во внешних файлах и т. д.... например, см. #adoptInstance:
.
Вместо этого вы должны научиться доверять пользователям вашей библиотеки (включая себя): пользователи не будут использовать basicNew
, если они не знают, что они делают (они узнают об этом рано или поздно). И, как сказал Амос, документируйте контракты и ожидания в комментариях к классам или сообщениям или модульных тестах, чтобы люди могли учиться быстрее, и, возможно, используйте не такие привлекательные имена, как basicNew, когда вы хотите выразить, что сообщение предназначено только для осведомленного использования.
EDIT кстати, если вы запретите basicNew, вы вообще не сможете создавать экземпляры, поэтому вам придется создать новое сообщение, вызывающее примитив для создания экземпляра, и в конце концов вы будет просто запутан/усложнен код ни за что, потому что вы просто сместили проблему. Если вы не делаете очень неприятных вещей, таких как:
basicNew
thisContext sender method selector == #mySepcialCreationMessageWithParameter: ifTrue: [^super basicNew].
^self error: 'new instances should be created with mySepcialCreationMessageWithParameter:'
Как я сказал выше, вы можете играть с этим, но не делайте этого по-настоящему.
РЕДАКТИРОВАТЬ 2 Другая точка зрения состоит в том, что программирование — это социальная деятельность, и код, который вы пишете на Smalltalk, предназначен не только для программирования автомата. Он предназначен для чтения и повторного использования людьми. В этом контексте защитное программирование чем-то похоже на управление посредством принуждения. Вместо того, чтобы тратить время на попытки ограничить, более эффективно потратить время на создание простых и логических абстракций, которые можно легко понять и использовать повторно, возможно, в других контекстах, которые вы не предусмотрели.
person
aka.nice
schedule
27.07.2017