В примере в FileReader принцип Лисков не соблюдается ни в первом, ни во втором варианте.
Вы поменяли класс на интерфейс, но EncryptedFileReader все еще усиливает предусловия (требует зашифрованный файл), в то время как IFileReader никак не описывает в контракте возможность исключений из-за того что файл "какой-то не такой".
Проблема здесь, на самом деле, в нарушении принципа SRP. EncryptedFileReader занимается одновременно и чтением файла, и дешифровкой. Эти две функциональности стоило бы разделить.
Банкам необязательно выдавать кредиты, чтобы обеспечить высокие ставки по вкладам.
ЦБ сам по себе дает кредиты и позволяет положить деньги на депозит. Ставка по кредитам равна ставке ЦБ+1%, ставка по депозитам равна ставке ЦБ-1%.
Вы кладете деньги в коммерческий банк на вклад под, скажем, 17%. Коммерческий банк эти же деньги перевкладывает под 20% в ЦБ и получает свои 3% профита.
Деньги, лежащие на депозитах в ЦБ, не участвуют в экономике и фактически изымаются из оборота.
но если вы улучшите отношение лестью, угрожая, унижая (как бы странно это не звучало)
Оскорбление в Морровинде не улучшает отношение персонажа. Никогда. Оскорбление используется для того, чтобы спровоцировать НПС напасть на героя. Тогда НПС можно убить, не вступая в конфликт с законом (а чо, это он первый начал!).
Но для того, чтобы оскорбление успешно сработало, нужно иметь прокачанный навык красноречия, плюс успешность сильно зависит от изначального отношения к персонажа к герою. Если персонаж изначально хорошо относится к персонажу, то и обижается на остроумную издевку быстрее. А если персонаж изначально относится к герою как к скрибовому желе, то и вялые подколы героя могут разве что насмешить тапочки персонажа (если вы понимаете, о чем я)
Если списки изначально вида arraylist, то удаление из списка хоть ты тресни будет неоптимально и вызывать реаллокации. Надо создавать новый arraylist result (сразу аллоцируя память размером Рекомендуемыe.size()) и по мере итерации добавлять отфильтрованные элементы в результирующий список.
Если изначально списки вида linkedlist, то там другая история
В задании вообще ничего не сказано о том, что возвращаемый результат функции должен быть элементом массива. Кое-как об этом можно догадаться по тестовым примерам, но, мягко говоря, с трудом.
И, например, совершенно не очевидно что f(a,2)=-1 - на первый взгляд f(a,2)=2 вполне валидно. Из условия задачи вообще не следует, что х за пределами массива является ошибкой.
Если речь именно о хулиганском срыве урока - это можно сделать и без смартфона, не вижу как особенно смартфон помогает кидаться бумажками в учителя или хамить.
А если 3-5 человек просто раздолбаи и отвлекаются от урока на игрушки в телефоне - ну пусть сядут на заднюю парту и играют себе тихо, мешать остальным они не будут.
В критичном случае деточка может получить люлей и оставить смартфон дома (для срочной связи можно выдать старую нокию). Именно этот вопрос как раз легко решается.
Это отличная идея с точки зрения технической оптимизации, но она обладает фундаментальным недостатком, а именно: если завтра критерий лояльности изменится с "посетил 2 страницы" на "посетил 3 страницы", то вам придется переписывать примерно все.
То есть подобную оптимизацию можно проводить, только трижды согласовав проблему с бизнесом: а нам точно-точно всегда-всегда будет достаточно двух страниц как критерия лояльности? Из моего опыта, даже если менеджер отвечает "точно да" на этот вопрос, верить ему не стоит, т.к. он банально не понимает жизни.
Совершенно верно. Задача "написать так чтобы было понятно" - вообще творческая, сложная. И, кстати, "понятно" отнюдь не означает "коротко".
В программировании этот вопрос отчасти решается введением огромного списка "терминов и определений". Это позволяет сократить каждый конкретный "пункт договора" до некоторой весьма удобоваримой длины, т.к. вся громоздкость уходит внутрь терминов. Однако, мгновенно встает проблема, что большинство "терминов и определений" оказываются запредельно сложны для понимания неподготовленным человеком.
Это как комментарии в коде. На первый взгляд вроде хорошо и полезно, но что делать, когда комментарий (по недосмотру али умыслу) начинает противоречить коду?
Надо код рефакторить, чтобы его можно было понятно читать, а не комментариями обкладываться.
Ну, я например, начал работу программистом C# в декабре 2010-го, в августе 2011-го пришел полным нулем в Android, в мае 2013-го уже работал по факту на сеньорской позиции (то есть полностью вел проект с технической стороны, хотя на тот момент еще не называл себя сеньором из скромности).
Надо сказать, что мне несколько повезло со специализацией - Android тогда только-только начал развиваться, и уже через полгода я был дефакто старшим разработчиком в компании и консультировал нанимаемых новеньких - не потому, что я сильно дофига знал по Android, но потому что я знал больше чем все остальные сотрудники в компании.
Так что я соглашусь с тем что лет 10 назад вкатываться в айти было попроще...
С этим тестом как раз все понятно, там чтения и потенциальная возможность/целесообразность их переупорядочивания вполне очевидна.
С п.2 все не так очевидно. Хотя, я, кажется, начинаю понимать, что вы имеете в виду.
Теоретически, можно предположить, что скомпилированный код
а) сначала прочитает значение переменной instance для использования в строке 90 return instance; В этот момент может прочитаться null
б) позднее еще раз прочитает значение переменной instance для использования в строке 87 if (instance == null), и в этот момент прочитается не-null
Так получается?
Теоретически, вроде бы, действительно я не вижу противоречия упомянутым правилам happens-before при таком раскладе. Но выглядит как-то совсем бредово...
Подумал третий раз и увидел, что в тех случаях, когда мы возвращаем объект mock, мы не делаем проверок на его содержимое и всегда возвращаем -1, так что моя гипотеза в п.1 скорее всего неактуальна (хотя стоило бы проверить на всякий случай)
Подумал еще раз и понял, что ситуацию с перестановкой местами вызова конструктора и присваивания ссылки мы также можем видеть и для instance = new Foo(); в строке 83. В этом случае строка 90 return instance; тоже может возвращать недозаполненный объект и триггерить outcome 0.
В п.2 чтения как раз таки связаны, и они не могут быть поменяны местами, т.к. это ломает консистентность в пределах одного потока. Точнее, сами чтения-то не связаны, а вот чтение + последующая return - очень даже связаны. Если в строке 87 instance == null выполняется, инструкция return instance; не может быть выполнена, ибо они в одном потоке.
А вот в процедуре создания объекта mock как раз таки возможна та самая перестановка, о которой я говорю в своем пункте 1, а вы - в своем последнем абзаце, когда вызов конструктора и присваивание ссылки на созданный объект меняются местами. В этом случае (очевидно предположить, что инициализация статической переменной mock случается в каком-то третьем потоке [утверждение требует проверки - ред.]) в строке 88 может быть возвращен "недозаполненный" объект mock, который триггерит @Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Object's data is null")
Так. Тут происходит что-то очень интересное, но не совсем очевидное.
1) Я так понимаю, что в некоторых случаях в ссылку Foo.mock оказывается записан валидный объект ДО того, как констуктор этого Foo.mock отработает. Ноооо... в каком треде происходит выполнение инструкции static final Foo mock = new Foo();и почему?
2) У вас в строке 90 приписан комментарий return instance; // can return null Это сбивает с толку - действительно ли в этой строке может вернуться null? Это же нарушает reordering в пределах одного потока. И в ваших тестах нет ни одного подобного случая.
В примере в
FileReader
принцип Лисков не соблюдается ни в первом, ни во втором варианте.Вы поменяли класс на интерфейс, но
EncryptedFileReader
все еще усиливает предусловия (требует зашифрованный файл), в то время какIFileReader
никак не описывает в контракте возможность исключений из-за того что файл "какой-то не такой".Проблема здесь, на самом деле, в нарушении принципа SRP.
EncryptedFileReader
занимается одновременно и чтением файла, и дешифровкой. Эти две функциональности стоило бы разделить.Банкам необязательно выдавать кредиты, чтобы обеспечить высокие ставки по вкладам.
ЦБ сам по себе дает кредиты и позволяет положить деньги на депозит. Ставка по кредитам равна ставке ЦБ+1%, ставка по депозитам равна ставке ЦБ-1%.
Вы кладете деньги в коммерческий банк на вклад под, скажем, 17%. Коммерческий банк эти же деньги перевкладывает под 20% в ЦБ и получает свои 3% профита.
Деньги, лежащие на депозитах в ЦБ, не участвуют в экономике и фактически изымаются из оборота.
Оскорбление в Морровинде не улучшает отношение персонажа. Никогда. Оскорбление используется для того, чтобы спровоцировать НПС напасть на героя. Тогда НПС можно убить, не вступая в конфликт с законом (а чо, это он первый начал!).
Но для того, чтобы оскорбление успешно сработало, нужно иметь прокачанный навык красноречия, плюс успешность сильно зависит от изначального отношения к персонажа к герою. Если персонаж изначально хорошо относится к персонажу, то и обижается на остроумную издевку быстрее. А если персонаж изначально относится к герою как к скрибовому желе, то и вялые подколы героя могут разве что насмешить тапочки персонажа (если вы понимаете, о чем я)
Если списки изначально вида arraylist, то удаление из списка хоть ты тресни будет неоптимально и вызывать реаллокации. Надо создавать новый arraylist result (сразу аллоцируя память размером Рекомендуемыe.size()) и по мере итерации добавлять отфильтрованные элементы в результирующий список.
Если изначально списки вида linkedlist, то там другая история
Разворачивая вашу мысль для тех, кто не понял:
В задании вообще ничего не сказано о том, что возвращаемый результат функции должен быть элементом массива. Кое-как об этом можно догадаться по тестовым примерам, но, мягко говоря, с трудом.
И, например, совершенно не очевидно что f(a,2)=-1 - на первый взгляд f(a,2)=2 вполне валидно. Из условия задачи вообще не следует, что х за пределами массива является ошибкой.
Если речь именно о хулиганском срыве урока - это можно сделать и без смартфона, не вижу как особенно смартфон помогает кидаться бумажками в учителя или хамить.
А если 3-5 человек просто раздолбаи и отвлекаются от урока на игрушки в телефоне - ну пусть сядут на заднюю парту и играют себе тихо, мешать остальным они не будут.
В критичном случае деточка может получить люлей и оставить смартфон дома (для срочной связи можно выдать старую нокию). Именно этот вопрос как раз легко решается.
Если 83% родителей против смартфонов в школах, что же они не запрещают своим детям использовать смартфоны на уроках?
Добавлю ссылку на свой же коммент на эту тему, но в другой ветке
Это отличная идея с точки зрения технической оптимизации, но она обладает фундаментальным недостатком, а именно: если завтра критерий лояльности изменится с "посетил 2 страницы" на "посетил 3 страницы", то вам придется переписывать примерно все.
То есть подобную оптимизацию можно проводить, только трижды согласовав проблему с бизнесом: а нам точно-точно всегда-всегда будет достаточно двух страниц как критерия лояльности? Из моего опыта, даже если менеджер отвечает "точно да" на этот вопрос, верить ему не стоит, т.к. он банально не понимает жизни.
Совершенно верно. Задача "написать так чтобы было понятно" - вообще творческая, сложная. И, кстати, "понятно" отнюдь не означает "коротко".
В программировании этот вопрос отчасти решается введением огромного списка "терминов и определений". Это позволяет сократить каждый конкретный "пункт договора" до некоторой весьма удобоваримой длины, т.к. вся громоздкость уходит внутрь терминов. Однако, мгновенно встает проблема, что большинство "терминов и определений" оказываются запредельно сложны для понимания неподготовленным человеком.
Это как комментарии в коде. На первый взгляд вроде хорошо и полезно, но что делать, когда комментарий (по недосмотру али умыслу) начинает противоречить коду?
Надо код рефакторить, чтобы его можно было понятно читать, а не комментариями обкладываться.
Ну, я например, начал работу программистом C# в декабре 2010-го, в августе 2011-го пришел полным нулем в Android, в мае 2013-го уже работал по факту на сеньорской позиции (то есть полностью вел проект с технической стороны, хотя на тот момент еще не называл себя сеньором из скромности).
Надо сказать, что мне несколько повезло со специализацией - Android тогда только-только начал развиваться, и уже через полгода я был дефакто старшим разработчиком в компании и консультировал нанимаемых новеньких - не потому, что я сильно дофига знал по Android, но потому что я знал больше чем все остальные сотрудники в компании.
Так что я соглашусь с тем что лет 10 назад вкатываться в айти было попроще...
И все же сложнее. Что проще - перефоткать на телефон 20 страниц текста или переслать один файл весом в пару мегабайт?
С этим тестом как раз все понятно, там чтения и потенциальная возможность/целесообразность их переупорядочивания вполне очевидна.
С п.2 все не так очевидно. Хотя, я, кажется, начинаю понимать, что вы имеете в виду.
Теоретически, можно предположить, что скомпилированный код
а) сначала прочитает значение переменной instance для использования в строке 90
return instance;
В этот момент может прочитаться nullб) позднее еще раз прочитает значение переменной instance для использования в строке 87
if (instance == null)
, и в этот момент прочитается не-nullТак получается?
Теоретически, вроде бы, действительно я не вижу противоречия упомянутым правилам happens-before при таком раскладе. Но выглядит как-то совсем бредово...
Подумал третий раз и увидел, что в тех случаях, когда мы возвращаем объект mock, мы не делаем проверок на его содержимое и всегда возвращаем -1, так что моя гипотеза в п.1 скорее всего неактуальна (хотя стоило бы проверить на всякий случай)
Подумал еще раз и понял, что ситуацию с перестановкой местами вызова конструктора и присваивания ссылки мы также можем видеть и для
instance = new Foo();
в строке 83. В этом случае строка 90return instance;
тоже может возвращать недозаполненный объект и триггерить outcome 0.Но возвращать null строка 90 все равно не может
Эмммм, по-моему вы заблуждаетесь.
В п.2 чтения как раз таки связаны, и они не могут быть поменяны местами, т.к. это ломает консистентность в пределах одного потока. Точнее, сами чтения-то не связаны, а вот чтение + последующая return - очень даже связаны. Если в строке 87
instance == null
выполняется, инструкцияreturn instance;
не может быть выполнена, ибо они в одном потоке.А вот в процедуре создания объекта mock как раз таки возможна та самая перестановка, о которой я говорю в своем пункте 1, а вы - в своем последнем абзаце, когда вызов конструктора и присваивание ссылки на созданный объект меняются местами. В этом случае (очевидно предположить, что инициализация статической переменной mock случается в каком-то третьем потоке [утверждение требует проверки - ред.]) в строке 88 может быть возвращен "недозаполненный" объект mock, который триггерит
@Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Object's data is null")
Так. Тут происходит что-то очень интересное, но не совсем очевидное.
1) Я так понимаю, что в некоторых случаях в ссылку Foo.mock оказывается записан валидный объект ДО того, как констуктор этого Foo.mock отработает. Ноооо... в каком треде происходит выполнение инструкции
static final Foo mock = new Foo();
и почему?2) У вас в строке 90 приписан комментарий
return instance; // can return null
Это сбивает с толку - действительно ли в этой строке может вернуться null? Это же нарушает reordering в пределах одного потока. И в ваших тестах нет ни одного подобного случая.А можно ссылочку на это самое федеральное законодательство? Какая именно статья устанавливает этот запрет?