Разное

Абстракция программирование: Зачем нужны абстракции и интерфейсы

Содержание

Зачем нужны абстракции и интерфейсы

Как в ста­ром анек­до­те: про объектно-ориентированное про­грам­ми­ро­ва­ние мож­но рас­ска­зать про­сто и непра­виль­но либо слож­но и непра­виль­но. Мы попро­бу­ем рас­ска­зать про оче­ред­ной аспект ООП просто. 

Зачем это: ООП — одна из глав­ных кон­цеп­ций совре­мен­ной раз­ра­бот­ки. Она при­ме­ни­ма не к каким-то кон­крет­ным язы­кам, это ско­рее спо­соб мыш­ле­ния в про­грам­ми­ро­ва­нии. Если вы пони­ма­е­те ООП, ваш код на любом язы­ке будет чище, чита­е­мее и эффективнее. 

В этой ста­тье раз­бе­рём два слож­ных поня­тия из объектно-ориентированного про­грам­ми­ро­ва­ния: абстрак­ции и интер­фей­сы. Это ещё одна сту­пень в пони­ма­нии непостижимого. 

Основные идеи из ООП
  • Объектно-ориентированное про­грам­ми­ро­ва­ние постро­е­но вокруг объ­ек­тов. Мож­но пред­ста­вить, что объ­ект — это короб­ка, в кото­рой лежат дан­ные и функции. 
  • Деле­ние на объ­ек­ты нуж­но для того, что­бы мож­но было созда­вать, обслу­жи­вать и пере­де­лы­вать части про­грам­мы, не влияя на дру­гие части и про­грам­му в целом. По-умному это назы­ва­ет­ся «для повы­ше­ния уров­ня абстракции». 
  • Смысл объ­ек­та в том, что он уме­ет делать какие-то свои дела, и осталь­ные объ­ек­ты не долж­ны знать, как он это делает.
  • У объ­ек­та есть поня­тие атри­бу­та и мето­да. Атри­бут — это любые дан­ные, кото­рые хра­нят­ся в «короб­ке» объ­ек­та. Мето­ды — это любые дей­ствия, кото­рые мож­но совер­шать над объ­ек­том или внут­ри его. Атри­бу­ты обыч­но выра­жа­ют­ся пере­мен­ны­ми, а мето­ды — функциями.
  • Объ­ек­ты необ­хо­ди­мы, напри­мер, в ком­пью­тер­ных играх, где каж­дая штуч­ка на игро­вом поле — это объ­ект с какими-то свой­ства­ми. Или в интернет-магазине, где один объ­ект отве­ча­ет за кор­зи­ну, дру­гой — за выклад­ку товара. 
  • Объ­ек­ты мож­но созда­вать по шаб­ло­ну — такие шаб­ло­ны назы­ва­ют­ся классами. 

Абстракция

Пред­ставь­те, что вы попро­си­ли несколь­ких чело­век опи­сать в общих чер­тах, что такое теле­фон и как им поль­зо­вать­ся: пусть это будут бабуш­ка, мама и подру­га. Бабуш­ка вспом­нит про дис­ко­вые теле­фо­ны и труб­ки с витым про­во­дом. Мама рас­ска­жет про радио­те­ле­фо­ны, у кото­рых есть база и есть труб­ка, с кото­рой мож­но ходить по всей квар­ти­ре, а подру­га нач­нёт опи­сы­вать мобильник.

Несмот­ря на то что рас­ска­зы будут силь­но отли­чать­ся меж­ду собой, у них будет несколь­ко общих момен­тов про телефон:

  • у теле­фо­на есть трубка;
  • в труб­ку мы гово­рим, из труб­ки — слушаем;
  • мож­но набрать номер нуж­но­го чело­ве­ка и позво­нить ему;
  • если вам позво­нят по теле­фо­ну, вы это услы­ши­те и при­ме­те звонок.

Полу­ча­ет­ся, что если пред­ста­вить абстракт­ный теле­фон, то полу­чит­ся такое устрой­ство с дина­ми­ком, мик­ро­фо­ном и сред­ством набо­ра номера. 

Это и есть абстрак­ция: когда мы опи­сы­ва­ем толь­ко самые суще­ствен­ные дета­ли, кото­рые важ­ны для зада­чи. В нашем слу­чае зада­ча такая — понять, что такое теле­фон и как им поль­зо­вать­ся. Поэто­му мик­ро­фон и дина­мик для этой зада­чи важен, а спо­соб свя­зи теле­фо­на с сетью — нет. Устрой­ство набо­ра номе­ра важ­но, а то, какая мело­дия игра­ет при вызо­ве — нет.

🔥 Абстрак­ция — это когда мы сосре­до­та­чи­ва­ем­ся толь­ко на суще­ствен­ных для зада­чи дета­лях и игно­ри­ру­ем всё осталь­ное. В ООП абстрак­ция озна­ча­ет, что для каж­до­го объ­ек­та мы зада­ём мини­маль­ное коли­че­ство мето­дов, полей и опи­са­ний, кото­рые поз­во­лят нам решить зада­чу. Чем мень­ше харак­те­ри­стик, тем луч­ше абстрак­ция, но клю­че­вые харак­те­ри­сти­ки уби­рать нельзя.

Что­бы рабо­тать с абстрак­ци­я­ми, исполь­зу­ют интерфейсы.

Интерфейс

Итак, у нас есть некое устрой­ство с труб­кой, мик­ро­фо­ном, дина­ми­ком и сред­ством набо­ра номе­ра. Но если вы вспом­ни­те рас­ска­зы мамы, бабуш­ки и подру­ги, то обна­ру­жи­те вот что:

  • в мик­ро­фон гово­рят, что­бы собе­сед­ник мог вас услышать;
  • что­бы слы­шать само­му, ухо при­кла­ды­ва­ют к динамику;
  • что­бы набрать номер, нуж­но с помо­щью номе­ро­на­би­ра­те­ля вызвать нуж­ную после­до­ва­тель­ность цифр;
  • когда идёт вызов, слыш­ны гуд­ки в динамике.

Всё это — интер­фей­сы. Они поз­во­ля­ют рабо­тать с объ­ек­том, не вни­кая в то, как он устро­ен внут­ри. Если вы уме­е­те рабо­тать с интер­фей­сом номе­ро­на­би­ра­те­ля, то вам всё рав­но, нуж­но ли кру­тить диск, нажи­мать физи­че­ские кноп­ки на радио­труб­ке или давить паль­цем на сен­сор­ный экран. 

Такой интер­фейс как бы гово­рит нам — я пере­дам в теле­фон любые циф­ры, какие захо­чешь. Как я это сде­лаю внут­ри и как они будут обра­бо­та­ны — неваж­но, про­сто набе­ри номер, а даль­ше теле­фон сам разберётся.

Интер­фей­сы — это дей­ствия над объ­ек­том, доступ­ные дру­гим объ­ек­там (поэто­му они назы­ва­ют­ся публичными). 

Есть ещё инкап­су­ли­ро­ван­ные, то есть внут­рен­ние мето­ды. Напри­мер, у мик­ро­фо­на есть пуб­лич­ный метод «Слу­шать голос», и есть внут­рен­ний метод «Пре­об­ра­зо­вать голос в элек­три­че­ские сиг­на­лы». С его помо­щью он вза­и­мо­дей­ству­ет с дру­ги­ми частя­ми наше­го абстракт­но­го теле­фо­на. Про инкап­су­ля­цию будет отдель­ный мате­ри­ал, пото­му что тема большая.

Сложная терминология

Стро­го гово­ря, интер­фей­сы — это не дей­ствия, а мето­ды. Сей­час объясним. 

В про­грам­ми­ро­ва­нии есть опе­ра­ции — это про­стей­шие дей­ствия, напри­мер, ско­пи­ро­вать зна­че­ние из одной пере­мен­ной в другую. 

Из про­стых дей­ствий состав­ля­ют­ся функ­ции — это когда несколь­ко опе­ра­ций «скле­и­ва­ют­ся» в нечто еди­ное. Мы даём этой склей­ке назва­ние и полу­ча­ем функ­цию. Напри­мер, может быть функ­ция «про­ве­рить пра­виль­ность элек­трон­но­го адре­са», кото­рая состо­ит из несколь­ких десят­ков про­стых операций. 

На язы­ке ООП функ­ции, при­вя­зан­ные к объ­ек­там, назы­ва­ют­ся мето­да­ми. Про­сто такой тер­мин. По сути это функ­ции, то есть скле­ен­ные вме­сте операции. 

Ито­го: метод — это набор про­стых дей­ствий, кото­рые скле­и­ли в еди­ное целое и засу­ну­ли в объект. 

Для чего это всё

Допу­стим, вы рабо­та­е­те в коман­де над боль­шим про­дук­том. В таких слу­ча­ях удоб­но раз­де­лить одну боль­шую про­грам­му на мно­же­ство мел­ких под­про­грамм и сер­ви­сов, каж­дый из кото­рых реша­ет свою узкую задачу.

Если зара­нее не дого­во­рить­ся о том, как эти ком­по­нен­ты обме­ни­ва­ют­ся дан­ны­ми меж­ду собой, то может слу­чить­ся то, о чём мы уже пре­ду­пре­жда­ли:

  • один про­грам­мист дела­ет функ­цию, кото­рая отве­ча­ет за реги­стра­цию новых пользователей;
  • все осталь­ные исполь­зу­ют эту функ­цию, при­вык­ли к её пара­мет­рам и зна­ют, что туда нуж­но передавать;
  • вне­зап­но этот про­грам­мист пони­ма­ет, что мож­но запро­грам­ми­ро­вать более эффек­тив­ный вари­ант реги­стра­ции, кото­рый будет рабо­тать гораз­до быстрее;
  • он пол­но­стью пере­пи­сы­ва­ет функ­цию, и в этот момент у всей коман­ды лома­ет­ся логи­ка про­грам­мы: ста­рые вызо­вы не рабо­та­ют, пото­му что функ­ция теперь при­ни­ма­ет дру­гие дан­ные (или в дру­гой последовательности).

Что­бы тако­го не было, посту­па­ют так:

  • Один про­грам­мист отве­ча­ет за реги­стра­цию новых пользователей.
  • Он дела­ет объ­ект «Поль­зо­ва­тель» и про­пи­сы­ва­ет ему интер­фейс «Заре­ги­стри­ро­вать».
  • Так­же он гово­рит, что интер­фейс «Заре­ги­стри­ро­вать» будет при­ни­мать на вход три пере­мен­ные: имя, почту и пароль.
  • Теперь про­грам­мист гово­рит осталь­ным: «Ребя­та, если нуж­но заре­ги­стри­ро­вать ново­го поль­зо­ва­те­ля — исполь­зуй­те интер­фейс Пользователь.Зарегистрировать(имя,почта,пароль)».
  • Даже если внут­ри объ­ек­та поме­ня­ет­ся вся логи­ка рабо­ты, то это никак не повли­я­ет на интер­фейс — все так же смо­гут им пользоваться.
  • А всё пото­му, что нико­му нет дела, как тот про­грам­мист реа­ли­зо­вал свою часть, если через интер­фейс всё рабо­та­ет нор­маль­но. Неваж­но, как он шиф­ру­ет пароль, где хра­нит почту, как обра­ба­ты­ва­ет имя и в какую базу дан­ных всё это скла­ды­ва­ет. Если интер­фейс рабо­та­ет, все осталь­ные могут про­дол­жать разработку.

Текст:
Миха­ил Полянин

Редак­тор:
Мак­сим Ильяхов

Худож­ник:
Даня Бер­ков­ский

Кор­рек­тор:
Ири­на Михеева

Вёрст­ка:
Мария Дро­но­ва

Соц­се­ти:
Олег Веш­кур­цев

Я не знаю ООП / Хабр

Я не умею программировать на объектно-ориентированных языках. Не научился. После 5 лет промышленного программирования на Java я всё ещё не знаю, как создать хорошую систему в объектно-ориентированном стиле. Просто не понимаю.

Я пытался научиться, честно. Я изучал паттерны, читал код open source проектов, пытался строить в голове стройные концепции, но так и не понял принципы создания качественных объектно-ориентированных программ. Возможно кто-то другой их понял, но не я.

И вот несколько вещей, которые вызывают у меня непонимание.

Я не знаю, что такое ООП

Серьёзно. Мне сложно сформулировать основные идеи ООП. В функциональном программировании одной из основных идей является отсутствие состояния. В структурном — декомпозиция. В модульном — разделение функционала в законченные блоки. В любой из этих парадигм доминирующие принципы распространяются на 95% кода, а язык спроектирован так, чтобы поощрять их использование. Для ООП я таких правил не знаю.

Принято считать, что объектно-ориентированное программирование строится на 4 основных принципах (когда я был мал, их было всего 3, но ведь тогда и деревья были большими). Эти принципы:

  • Абстракция
  • Инкапсуляция
  • Наследование
  • Полиморфизм

Смахивает на свод правил, не так ли? Значит вот оно, те самые правила, которым нужно следовать в 95% случаев? Хмм, давайте посмотрим поближе.

Абстракция

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

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

Во-вторых, абстракции в программировании были всегда, начиная с записей Ады Лавлейс, которую принято считать первым в истории программистом. С тех пор люди бесперерывно создавали в своих программах абстракции, зачастую имея для этого лишь простейшие средства. Так, Абельсон и Сассман в своей небезызвестной книге описывают, как создать систему решения уравнений с поддержкой комплексных чисел и даже полиномов, имея на вооружении только процедуры и связные списки. Так какие же дополнительные средства абстрагирования несёт в себе ООП? Понятия не имею. Выделение кода в подпрограммы? Это умеет любой высокоуровневый язык. Объединение подпрограмм в одном месте? Для этого достаточно модулей. Типизация? Она была задолго до ООП. Пример с системой решения уравнений хорошо показывает, что построение уровней абстракции не столько зависит от средств языка, сколько от способностей программиста.

Инкапсуляция

Главный козырь инкапсуляции в сокрытии реализации. Клиентский код видит только интерфейс, и только на него может рассчитывать.

Это развязывает руки разработчикам, которые могут решить изменить реализацию. И это действительно круто. Но вопрос опять же в том, причём тут ООП? Все вышеперечисленные парадигмы подразумевают сокрытие реализации. Программируя на C вы выделяете интерфейс в header-файлы, Oberon позволяет делать поля и методы локальными для модуля, наконец, абстракция во многих языках строится просто посредствам подпрограмм, которые также инкапсулируют реализацию. Более того, объектно-ориентированные языки сами зачастую нарушают правило инкапсуляции, предоставляя доступ к данным через специальные методы — getters и setters в Java, properties в C# и т.д. (В комментариях выяснили, что некоторые объекты в языках программирования не являются объектами с точки зрения ООП: data transfer objects отвечают исключительно за перенос данных, и поэтому не являются полноценными сущностями ООП, и, следовательно, для них нет необходимости сохранять инкапсуляцию. С другой стороны, методы доступа лучше сохранять для поддержания гибкости архитектуры.
Вот так всё непросто.) Более того, некоторые объектно-ориентированные языки, такие как Python, вообще не пытаются что-то скрыть, а расчитывают исключительно на разумность разработчиков, использующих этот код.

Наследование

Наследование — это одна из немногих новых вещей, которые действительно вышли на сцену благодаря ООП. Нет, объектно-ориентированные языки не создали новую идею — наследование вполне можно реализовать и в любой другой парадигме — однако ООП впервые вывело эту концепцию на уровень самого языка. Очевидны и плюсы наследования: когда вас почти устраивает какой-то класс, вы можете создать потомка и переопределить какую-то часть его функциональности. В языках, поддерживающих множественное наследование, таких как C++ или Scala (в последней — за счёт traits), появляется ещё один вариант использования — mixins, небольшие классы, позволяющие «примешивать» функциональность к новому классу, не копируя код.

Значит, вот оно — то, что выделяет ООП как парадигму среди других? Хмм… если так, то почему мы так редко используем его в реальном коде? Помните, я говорил про 95% кода, подчиняющихся правилам доминирующей парадигмы? Я ведь не шутил. В функцинальном программировании не меньше 95% кода использует неизменяемые данные и функции без side-эффектов. В модульном практически весь код логично расфасован по модулям. Преверженцы структурного программирования, следуя заветам Дейкстры, стараются разбивать все части программы на небольшие части. Наследование используется гораздо реже. Может быть в 10% кода, может быть в 50%, в отдельных случаях (например, при наследовании от классов фреймворка) — в 70%, но не больше. Потому что в большинстве ситуаций это просто

не нужно.

Более того, наследование опасно для хорошего дизайна. Настолько опасно, что Банда Четырех (казалось бы, проповедники ООП) в своей книге рекомендуют при возможности заменять его на делегирование. Наследование в том виде, в котором оно существует в популярных ныне языках ведёт к хрупкому дизайну. Унаследовавшись от одного предка, класс уже не может наследоваться от других. Изменение предка так же становится опасным. Существуют, конечно, модификаторы private/protected, но и они требуют неслабых экстрасенсорных способностей для угадывания, как класс может измениться и как его может использовать клиентский код. Наследование настолько опасно и неудобно, что крупные фреймворки (такие как Spring и EJB в Java) отказываются от них, переходя на другие, не объектно-ориентированные средства (например, метапрограммирование). Последствия настолько непредсказуемы, что некоторые библиотеки (такие как Guava) прописывает своим классам модификаторы, запрещающие наследование, а в новом языке Go было решено вообще отказаться от иерархии наследования.

Полиморфизм

Пожалуй, полиморфизм — это лучшее, что есть в объектно-ориентированном программировании. Благодаря полиморфизму объект типа Person при выводе выглядит как «Шандоркин Адам Имполитович», а объект типа Point — как «[84.23 12.61]». Именно он позволяет написать «Mat1 * Mat2» и получить произведение матриц, аналогично произведению обычных чисел. Без него не получилось бы и считывать данные из входного потока, не заботясь о том, приходят они из сети, файла или строки в памяти. Везде, где есть интерфейсы, подразумевается и полиморфизм.

Мне правда нравится полиморфизм. Поэтому я даже не стану говорить о его проблемах в мейнстримовых языках. Я также промолчу про узость подхода диспетчеризации только по типу, и про то, как это могло бы быть сделано. В большинстве случаев он работает как надо, а это уже неплохо. Вопрос в другом: является ли полиморфизм тем самым принципом, отличающим ООП от других парадигм? Если бы вы спросили меня (а раз уж вы читаете этот текст, значит, можно считать, что спросили), я бы ответил «нет». И причина всё в тех же процентах использования в коде. Возможно, интерфейсы и полиморфные методы встречаются немного чаще наследования. Но сравните количество строк кода, занимаемое ими, с количеством строк, написанных в обычном процедурном стиле — последних всегда больше. Глядя на языки, поощряющие такой стиль программирования, я не могу назвать их полиморфными. Языки с поддержкой полиморфизма — да, так нормально. Но не полиморфные языки.

(Впрочем, это моё мнение. Вы всегда можете не согласиться.)

Итак, абстракция, инкапсуляция, наследование и полиморфизм — всё это есть в ООП, но ничто из этого не является его неотъемлемым атрибутом.

Тогда что такое ООП? Есть мнение, что суть объектно-ориентированного программирования лежит в, собственно, объектах (звучит вполне логично) и классах. Именно идея объединения кода и данных, а также мысль о том, что объекты в программе отражают сущности реального мира. К этому мнению мы ещё вернёмся, но для начала расставим некоторые точки над i.

Чьё ООП круче?

Из предыдущей части видно, что языки программирования могут сильно отличаться по способу реализации объектно-ориентированного программирования. Если взять совокупность всех реализаций ООП во всех языках, то вероятнее всего вы не найдёте вообще ни одной общей для всех черты. Чтобы как-то ограничить этот зоопарк и внести ясность в рассуждения, я остановлюсь только одной группе — чисто объекто-ориентированные языки, а именно Java и C#. Термин «чисто объектно-ориентированный» в данном случае означает, что язык не поддерживает другие парадигмы или реализует их через всё то же ООП. Python или Ruby, например, не буду являться чистыми, т.
к. вы вполне можете написать полноценную программу на них без единого объявления класса.

Чтобы лучше понять суть ООП в Java и C#, пробежимся по примерам реализации этой парадигмы в других языках.

Smalltalk. В отличие от своих современных коллег, этот язык имел динамическую типизацию и использовал message-passing style для реализации ООП. Вместо вызовов методов объекты посылали друг другу сообщения, а если получатель не мог обработать то, что пришло, он просто пересылал сообщение кому-то ещё.

Common Lisp. Изначально CL придерживался такой же парадигмы. Затем разработчики решили, что писать `(send obj ‘some-message)` — это слишком долго, и преобразовали нотацию в вызов метода — `(some-method obj)`. На сегодняшний день Common Lisp имеет развитую систему объектно-ориентированного программирования (CLOS) с поддержкой множественного наследования, мультиметодов и метаклассов. Отличительной чертой является то, что ООП в CL крутится не вокруг объектов, а вокруг обобщённых функций.

Clojure. Clojure имеет целых 2 системы объектно-ориентированного программирования — одну, унаследованную от Java, и вторую, основанную на мультиметодах и более похожую на CLOS.

R. Этот язык для статистического анализа данных также имеет 2 системы объектно-ориентированного программирования — S3 и S4. Обе унаследованы от языка S (что не удивительно, учитывая, что R — это open source реализация коммерческого S). S4 по большей части соотвествует реализациям ООП в современных мейнстримовых языках. S3 является более легковесным вариантом, элементарно реализуемым средствами самого языка: создаётся одна общая функция, диспетчеризирующая запросы по атрибуту «class» полученного объекта.

JavaScript. По идеологии похож на Smalltalk, хотя и использует другой синтаксис. Вместо наследования использует прототипирование: если искомого свойства или вызванного метода в самом объекте нет, то запрос передаётся объекту-прототипу (свойство prototype всех объектов JavaScript). Интересным является факт, что поведение всех объектов класса можно поменять, заменив один из методов прототипа (очень красиво, например, выглядит добавление метода `.toBASE64` для класса строки).

Python. В целом придерживается той же концепции, что и мейнcтримовые языки, но кроме этого поддерживает передачу поиска атрибута другому объекту, как в JavaScript или Smalltalk.

Haskell. В Haskell вообще нет состояния, а значит и объектов в обычном понимании. Тем не менее, своеобразное ООП там всё-таки есть: типы данных (types) могут принадлежать одному или более классам типов (type classes). Например, практически все типы в Haskell состоят в классе Eq (отвечает за операции сравнения 2-х объектов), а все числа дополнительно в классах Num (операции над числами) и Ord (операции <, <=, >=, >). В менстримовых языках типам соответствуют классы (данных), а классам типов — интерфейсы.

Stateful или Stateless?

Но вернёмся к более распространённым системам объектно-ориентированного программирования. Чего я никогда не мог понять, так это отношения объектов с внутренним состоянием. До изучения ООП всё было просто и прозрачно: есть структуры, хранящие несколько связанных данных, есть процедуры (функции), их обрабатывающие. выгулять(собаку), снятьс(аккаунт, сумма). Потом пришли объекты, и это было тоже ничего (хотя читать программы стало гораздо сложней — моя собака выгуливала [кого?], а аккаунт снимал деньги [откуда?]). Затем я узнал про сокрытие данных. Я всё ещё мог выгулять собаку, но вот посмотреть состав её пищи уже не мог. Пища не выполняла никаких действий (наверное, можно было написать, что пища.съесть(собака), но я всё-таки предпочитаю, чтобы моя собака ела пищу, а не наоборот). Пища — это просто данные, а мне (и моей собаке) нужно было просто получить к ним доступ. Всё просто. Но в рамки парадигмы влезть было уже невозможно, как в старые джинсы конца 90-х.

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

Не успел я насладиться просветлением, как увидил в интернетах слово stateless (готов поклясться, оно было окружено сиянием, а над буквами t и l висел нимб). Короткое изучение литературы открыло чудесный мир прозрачного потока управления и простой многопоточности без необходимости отслеживать согласованность объекта. Конечно, мне сразу захотелось прикоснуться к этому чудесному миру. Однако это означало полный отказ от любых правил — теперь было непонятно, следует ли собаке самой себя выгуливать, или для этого нужен специальный ВыгулМенеджер; нужен ли аккаунт, или со всей работой справится Банк, а если так, то должен он списывать деньги статически или динамически и т.д. Количество вариантов использования возрасло экспоненциально, и все варианты в будущем могли привести к необходимости серьёзного рефакторинга.

Я до сих пор не знаю, когда объект следует сделать stateless, когда stateful, а когда просто контейнером данных. Иногда это очевидно, но чаще всего нет.

Типизация: статическая или динамическая?

Еща одна вещь, с которой я не могу определиться относительно таких языков, как C# и Java, это являются они статически или динамически типизированными. Наверное большинство людей воскликнет «Что за глупость! Конечно статически типизированными! Типы проверяются во время компиляции!». Но действительно ли всё так просто? Правда ли, что программист, прописывая в параметрах метода тип X может быть уверен, что в него всегда будут передаваться объекты именно типа X? Верно — не может, т.к. в метод X можно будет передать параметр типа X или его наследника. Казалось бы, ну и что? Наследники класса X всё равно будут иметь те же методы, что и X. Методы методами, а вот логика работы может оказаться совершенно другой. Самый распространённый случай, это когда дочерний класс оказывается соптимизированным под другие нужды, чем X, а наш метод может рассчитывать именно на ту оптимизацию (если вам такой сценарий кажется нереалистичным, попробуйте написать плагин к какой-нибудь развитой open source библиотеке — либо вы потратите несколько недель на разбор архитектуры и алгоритмов библиотеки, либо будете просто наугад вызывать методы с подходящей сигнатурой). В итоге программа работает, однако скорость работы падает на порядок. Хотя с точки зрения компилятора всё корректно. Показательно, что Scala, которую называют наследницей Java, во многих местах по умолчанию разрешает передавать только аргументы именно указанного типа, хотя это поведение и можно изменить.

Другая проблема — это значение null, которое может быть передано практически вместо любого объекта в Java и вместо любого Nullable объекта в C#. null принадлежит сразу всем типам, и в то же время не принадлежит ни одному. null не имеет ни полей, ни методов, поэтому любое обращение к нему (кроме проверки на null) приводит к ошибке. Вроде бы все к этому привыкли, но для сравнения Haskell (да и та же Scala) заставлют использовать специальные типы (Maybe в Haskell, Option в Scala) для обёртки функций, которые в других языках могли бы вернуть null. В итоге про Haskell часто говорят «скомпилировать программу на нём сложно, но если всё-таки получилось, значит скорее всего она работает корректно».

С другой стороны, мейнстримовые языки, очевидно, не являются динамически типизированными, а значит не обладают такими свойствами, как простота интерфейсов и гибкость процедур. В итоге писать в стиле Python или Lisp также становится невозможным.

Какая разница, как называется такая типизация, если все правила всё равно известны? Разница в том, с какой стороны подходить к проектированию архитектуры. Существует давний спор, как строить систему: делать много типов и мало функций, или мало типов и много функций? Первый подход активно используется в Haskell, второй в Lisp. В современных объектно-ориентированных языках используется что-то среднее. Я не хочу сказать, что это плохо — наверное у него есть свои плюсы (в конце концов не стоит забывать, что за Java и C# стоят мультиязыковые платформы), но каждый раз приступая к новому проекту я задумываюсь, с чего начать проектирования — с типов или с функционала.

И ещё…

Я не знаю, как моделировать задачу. Считается, что ООП позволяет отображать в программе объекты реального мира. Однако в реальности у меня есть собака (с двумя ушами, четырмя лапами и ошейником) и счёт в банке (с менеджером, клерками и обеденным перерывом), а в программе — ВыгулМенеджер, СчётФабрика… ну, вы поняли. И дело не в том, что в программе есть вспомогательные классы, не отражающие объекты реального мира. Дело в том, что поток управления изменяется. ВыгулМенеджер лишает меня удовольствия от прогулки с собакой, а деньги я получаю от бездушного БанкСчёта (эй, где та милая девушка, у которой я менял деньги на прошлой неделе?).

Может быть я сноб, но мне было гораздо приятней, когда данные в компьютере были просто данными, даже если описывали мою собаку или счёт в банке. С данными я мог сделать то, что удобно, без оглядки на реальный мир.

Я также не знаю, как правильно декомпозировать функционал. В Python или C++, если мне нужна была маленькая функция для преобразования строки в число, я просто писал её в конце файла. В Java или C# я вынужден выносить её в отдельный класс StringUtils. В недо-ОО-языках я мог объявить ad hoc обёртку для возврата двух значений из функции (снятую сумму и остаток на счету). В ООП языках мне придётся создать полноценный класс РезультатТранзакции. И для нового человека на проекте (или даже меня самого через неделю) этот класс будет выглядеть точно таким же важным и фундаментальным в архитектуре системы. 150 файлов, и все одинаково важные и фундаментальные — о да, прозрачная архитектура, прекрасные уровни абстракции.

Я не умею писать эффективные программы. Эффективные программы используют мало памяти — иначе сборщик мусора будет постоянно тормозить выполнение. Но чтобы совершить простейшую операцию в объектно-ориентированных языках приходится создавать дюжину объектов. Чтобы сделать один HTTP запрос мне нужно создать объект типа URL, затем объект типа HttpConnection, затем объект типа Request… ну, вы поняли. В процедурном программировании я бы просто вызвал несколько процедур, передав им созданную на стеке структуру. Скорее всего, в памяти был бы создан всего один объект — для хранения результата. В ООП мне приходится засорять память постоянно.

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

8) Абстракция данных — CoderLessons.com

Что такое абстракция в ООП?

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

Нажмите здесь, если видео не доступно

Давайте изучим концепцию абстракции на примере

Предположим, вы хотите создать банковское приложение, и вас попросят собрать всю информацию о вашем клиенте. Есть вероятность, что вы получите следующую информацию о клиенте

Но не вся вышеуказанная информация требуется для создания банковского приложения.

Таким образом, вам нужно выбрать из этого пула только полезную информацию для вашего банковского приложения. Такие данные, как имя, адрес, налоговая информация и т. Д. Имеют смысл для банковского приложения

Поскольку мы извлекли / удалили / выбрали информацию о клиенте из большого пула, этот процесс называется абстракцией.

Однако одна и та же информация после извлечения может быть использована для широкого спектра применений. Например, вы можете использовать одни и те же данные для приложения больницы, приложения портала работы, правительственной базы данных и т. Д. Практически без изменений. Следовательно, он становится вашими основными данными. Это преимущество абстракции.

Что такое абстракция в Java?

Абстракция в JAVA «показывает» только необходимые атрибуты и «скрывает» ненужные детали объекта от пользователя. В Java абстракция выполняется с использованием абстрактных классов, абстрактных методов и интерфейсов. Абстракция помогает уменьшить сложность и трудоемкость программирования.

Абстрактный класс

Класс, который объявлен «абстрактным», называется абстрактным классом. Он может иметь как абстрактные методы, так и конкретные методы. Нормальный класс не может иметь абстрактных методов.

Абстрактный метод

Метод без тела известен как абстрактный метод. Он должен быть объявлен в абстрактном классе. Абстрактный метод никогда не будет окончательным, потому что абстрактный класс должен реализовывать все абстрактные методы.

Правила абстрактного метода

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

Разница между абстракцией и инкапсуляцией

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

Разница между абстрактным классом и интерфейсом

Абстрактный классИнтерфейс

Абстрактный класс может иметь как абстрактные, так и неабстрактные методы.

Интерфейс может иметь только абстрактные методы.

Он не поддерживает множественное наследование.

Он поддерживает множественное наследование.

Это может обеспечить реализацию интерфейса.

Он не может обеспечить реализацию абстрактного класса.

Абстрактный класс может иметь защищенные и абстрактные публичные методы.

Интерфейс может иметь только публичные абстрактные методы.

Абстрактный класс может иметь конечную, статическую или статическую конечную переменную с любым спецификатором доступа.

Интерфейс может иметь только открытую статическую переменную final.

Преимущества абстракции

  • Основное преимущество использования абстрактного класса состоит в том, что он позволяет группировать несколько связанных классов как братьев и сестер.
  • Абстракция помогает снизить сложность процесса проектирования и внедрения программного обеспечения.

Когда использовать абстрактные методы и абстрактный класс?

Абстрактные методы в основном объявляются, когда два или более подклассов также делают одно и то же по-разному через разные реализации. Он также расширяет тот же класс Abstract и предлагает различные реализации абстрактных методов.

Абстрактные классы помогают описать универсальные типы поведения и иерархию классов объектно-ориентированного программирования. Он также описывает подклассы, чтобы предложить детали реализации абстрактного класса.

Резюме:

  • Абстракция — это процесс выбора важных наборов данных для Объекта в вашем программном обеспечении и исключения незначительных.
  • После того как вы смоделировали свой объект с помощью Abstraction, один и тот же набор данных может использоваться в разных приложениях.
  • Java, абстракция осуществляется с использованием абстрактных классов и интерфейсов. Мы будем подробно изучать абстрактные классы и интерфейсы в следующих уроках.

 

Шпаргалка по принципам ООП

Главное

  • Инкапсулируйте все, что может изменяться;
  • Уделяйте больше внимания интерфейсам, а не их реализациям;
  • Каждый класс в вашем приложении должен иметь только одно назначение;
  • Классы — это их поведение и функциональность.

Базовые принципы ООП

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

Используйте следующее вместе с наследованием

  • Делегация — перепоручение задачи от внешнего объекта внутреннему;
  • Композиция — включение объектом-контейнером объекта-содержимого и управление его поведением; последний не может существовать вне первого;
  • Агрегация — включение объектом-контейнером ссылки на объект-содержимое; при уничтожении первого последний продолжает существование.

Не повторяйся (Don’t repeat yourself — DRY)

Избегайте повторного написания кода, вынося в абстракции часто используемые задачи и данные. Каждая часть вашего кода или информации должна находиться в единственном числе в единственном доступном месте. Это один из принципов читаемого кода.

Принцип единственной обязанности

Для каждого класса должно быть определено единственное назначение. Все ресурсы, необходимые для его осуществления, должны быть инкапсулированы в этот класс и подчинены только этой задаче.

Принцип открытости/закрытости

Программные сущности должны быть открыты для расширения, но закрыты для изменений.

Принцип подстановки Барбары Лисков

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

Принцип разделения интерфейсов

Предпочтительнее разделять интерфейсы на более мелкие тематические, чтобы реализующие их классы не были вынуждены определять методы, которые непосредственно в них не используются.

Принцип инверсии зависимостей

Система должна конструироваться на основе абстракций «сверху вниз»: не абстракции должны формироваться на основе деталей, а детали должны формироваться на основе абстракций.

Перевод статьи «Object-Orientated Design Principles»

 

Что означает абстракция в программировании?

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

Что такое абстракция

Абстрагировать что-то означает давать имена вещам, так что имя отражает суть того, что делает функция или целая программа.

Один пример приведен в книге, на которую вы ссылаетесь, где говорится:

Предположим, мы работаем с черепахами, и общая операция, которая нам нужна , — это рисование квадратов. “Draw a square”-это абстракция, или мысленный кусок, из ряда меньших шагов. Итак, давайте напишем функцию, чтобы захватить шаблон этого » строительного блока”:

Забудьте на минуту о черепахах и просто подумайте о том, чтобы нарисовать квадрат. Если я скажу вам нарисовать квадрат (на бумаге), вы сразу же узнаете, что делать:

  • нарисуйте квадрат = > нарисуйте прямоугольник со всеми сторонами одинаковой длины.

Вы можете сделать это без дальнейших вопросов, потому что вы знаете наизусть, Что такое квадрат , без того, чтобы я рассказывал вам шаг за шагом. Здесь слово квадрат является абстракцией «draw a rectangle with all sides of the same length».

Абстракции уходят глубоко

Но постойте, откуда вы знаете, что такое прямоугольник ? Ну, это еще одна абстракция для следующего:

  • нарисуйте две параллельные друг другу линии одинаковой длины, а затем добавьте еще две параллельные линии, перпендикулярные двум другим линиям, снова той же длины, но, возможно, другой длины, чем первые две.

Конечно, это продолжается и продолжается — линии, параллельные, перпендикулярные, соединяющие -все это абстракции известных понятий.

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

Реальная сила абстракции

Это первая сила абстракций: они значительно облегчают разговор и выполнение задач.

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

  • дом = > нарисуйте квадрат с треугольником сверху

Далее, вы хотите деревню:

  • деревня => нарисуйте несколько домов рядом друг с другом

О, Подождите, мы хотим город — и у нас есть новая концепция улицы :

  • город = > нарисуйте много деревень близко друг к другу, заполните пустые пространства большим количеством домов , но оставьте место для улиц
  • улица = > (некоторое определение улицы)

и так далее. ..

Как все это относится к программированию?

Если в процессе планирования вашей программы (процесс, известный как анализ и проектирование) вы находите хорошие абстракции для проблемы, которую вы пытаетесь решить, ваши программы становятся короче, следовательно, их легче писать и, возможно, что более важно, легче читать. Способ сделать это-попытаться понять основные понятия , которые определяют ваши проблемы-как в (упрощенном) примере рисования дома , это были квадраты и треугольники, чтобы нарисовать деревню , это были дома .

В программировании мы определяем абстракции как функции (и некоторые другие конструкции, такие как классы и модули, но давайте пока сосредоточимся на функциях). Функция по существу называет набор отдельных операторов, поэтому функция по существу является абстракцией — Подробнее см. примеры в вашей книге.

Красота всего этого

В программировании абстракции могут повышать или снижать производительность. Вот почему часто часто используемые функции собираются в библиотеки , которые могут быть повторно использованы другими. Это означает, что вам не нужно беспокоиться о деталях, вам нужно только понять, как использовать готовые абстракции. Очевидно, что это должно облегчить вам задачу, чтобы вы могли работать быстрее и, следовательно, быть более продуктивными:

Пример :

Представьте себе, что существует графическая библиотека под названием «nicepic», которая содержит заранее определенные функции для всех абстракций, рассмотренных выше: прямоугольники, квадраты, треугольники, дом, деревня.

Скажем, вы хотите создать программу, основанную на вышеуказанных абстракциях, которая рисует красивую картину дома, все, что вам нужно написать, это:

import nicepic
draw_house()

Так что это всего лишь две строки кода, чтобы получить что-то гораздо более сложное. Разве это не замечательно?

Надеюсь, это поможет.

Абстракция списков — Intermediate Python

Абстракции — это та особенность Python, которой мне будет очень сильно недоставать, если я сменю язык программирования. Абстракции — это конструкторы, позволяющие создавать последовательности из других последовательностей. В Python (2 и 3) есть три типа подобных абстракций:

  • абстракции списков

  • абстракции словарей

  • абстракции множеств

  • абстракции генераторов

Мы обсудим все три, хотя освоив абстракции списков вы легко перенесёте знания на остальные типы.

Абстракции списков открывают доступ к простому и лаконичному синтаксису генерации списков. Конструкция состоит из квадратных скобок содержащих выражение и оператор for, плюс дополнительные for или if при необходимости. Выражения могут быть любыми, т.е. вам разрешается иметь любые элементы внутри списка. Результатом работы будет новый список после исполнения выражения с оглядкой на for и if.

Шаблон использования:

variable = [out_exp for out_exp in input_list if out_exp == 2]

Вот короткий пример:

multiples = [i for i in range(30) if i % 3 == 0]

print(multiples)

Такой синтаксис может быть очень удобен для быстрого создания списков. Использование такого подхода вместо функции filter позволяет повысить читаемость кода (без потери скорости исполнения). Особенно хорошо абстракции списков заменяют создание нового простого списка при помощи цикла for и append. Наглядный пример:

squared = []

for x in range(10):

squared.append(x**2)

Вы можете сократить решение до одной строки:

squared = [x**2 for x in range(10)]

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

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}

mcase_frequency = {

k. lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)

for k in mcase.keys()

}

В примере выше мы суммируем значения ключей, которые отличаются только регистром. Лично я редко пользуюсь этим методом. Вы также можете легко поменять местами ключи и значения в словаре:

{v: k for k, v in some_dict.items()}

Абстракции множеств схожи с абстракциями списков. Единственное различие — используются фигурные скобки {}. Вот пример:

squared = {x**2 for x in [1, 1, 2]}

print(squared)

Абстракции генераторов похожи на абстракции списков. Единственное отличие — генераторы не выделяют память сразу под все элементы, а возвращают их один за одним, что намного более экономно:

multiples_gen = (i for i in range(30) if i % 3 == 0)

print(multiples_gen)

for x in multiples_gen:

print(x)

В русскоязычном сегменте интернета распространение получили другие названия абстракций, в частности используются понятия генераторы списков/словарей/множеств. Данные термины, однако, не совсем корректны, так как не являются генераторами (здесь возможна путаница с genexp, т.е. (x**2 for x in [1, 2, 3]) — генераторное выражение, возвращающее объект генератора). В английском используется list/dict/set comprehension (comprehension — включение). Рекомендуется использовать либо вариант списковые включения, либо английское название или его краткую форму listcomp/dictcomp/setcomp.

Закон дырявых абстракций — блог Selectel

Текст, который установил «закон дырявых абстракций», был написан в 2002 году. Почему я перевожу его спустя почти 20 лет? Он до сих пор не потерял своей актуальности и достоин прочтения.

Протокол TCP не получил лучшую альтернативу, а закон дырявых абстракций лишь укрепился в жизни разработчиков и рискует стать аксиомой. Добавлю, что я не пересчитывал все указанные в тексте временные рамки, так что учитывайте некоторый «сдвиг во времени».

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

Использование протокола TCP — это способ надежно передать данные. Поясню: использование TCP при пересылке сообщения через сеть гарантирует, что оно будет доставлено в первоначальном виде.

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

Для сравнения, существует другой, ненадежный, протокол передачи данных под названием IP. Никто не дает гарантий, что данные будут доставлены. Если вы отправите последовательность сообщений с использованием IP, то не удивляйтесь, когда половина сообщений не будет доставлена, а вторая половина придет в случайном порядке. Более того, есть шанс, что часть сообщений превратится в изображения маленьких обезьянок или, что вероятнее, сообщения станут нечитаемым мусором.

Вот здесь-то и происходит настоящее волшебство: TCP работает на основе IP. Иными словами, TCP обязан доставить данные надежно, используя только ненадежный инструмент.

Чтобы стало понятнее, почему это волшебство, рассмотрим приближенный к реальности, хоть и несколько нелепый сценарий из жизни.

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

Теперь представьте сервис Hollywood Express, который гарантирует: (а) доставку; (б) в правильном порядке; (в) в идеальном состоянии. Чудеса заключаются в том, что у Hollywood Express нет иных способов трансфера актеров, кроме ненадежного — на машинах. Hollywood Express проверяет каждого приезжающего актера, и если его состояние неудовлетворительно, то сервис звонит на родину актера и просит выслать идентичного близнеца. Если актеры приезжают в случайном порядке, то Hollywood Express восстановит изначальный порядок. Даже если большой корабль пришельцев на своем пути в Зону 51 упадет и парализует скоростную магистраль в Неваде, актеры просто сменят маршрут и поедут через Аризону, а Hollywood Express ничего не скажет об инциденте продюсерам в Калифорнии. Для продюсеров все будет выглядеть так, будто актеры ехали чуть дольше обычного и никакого крушения НЛО не было.

Примерно так же работает TCP. Это то, что специалисты в Computer Science называют абстракцией — упрощением чего-то значительно более сложного, происходящего «под капотом». Большая часть программирования заключается в построении абстракций. Что такое библиотека для работы со строками? Это способ сделать работу со строками такой же простой и удобной, как и с числами. Что такое файловая система? Это способ представить жесткий диск не набором вращающихся магнитных пластин, хранящих биты в определенных местах, а иерархической структурой каталогов с файлами, которые содержат данные.

Но вернемся к TCP. Я немного приукрасил, чтобы облегчить понимание работы TCP. И осознаю, что некоторых такое упрощение может довести до белого каления. Я сказал, что TCP гарантирует доставку сообщения. Что ж, это не так. Если ваш домашний питомец перегрызет сетевой кабель вашего компьютера, то IP-пакеты перестанут его достигать. Вне зависимости от усилий TCP сообщение не будет доставлено. Если вы были невежливы с системными администраторами в вашей компании и вас решили наказать, подключив к перегруженному концентратору, то лишь часть ваших IP-пакетов будет доходить, в этом случае TCP будет работать, но чрезвычайно медленно.

Именно это я и называю дырявыми абстракциями. Протокол TCP пытается абстрагировать нас от ненадежной сети, но иногда сеть все равно «протекает» через абстракцию и вы встречаетесь с вещами, от которых абстракция не может вас спасти. Это всего лишь один пример того, что я называю Законом Дырявых Абстракций:

Любая нетривиальная абстракция в некоторой степени дырявая.

Абстракции ломаются. Иногда немного, иногда значительно. Это и называется дырами, протечками. Что-то идет не по плану. Это происходит повсеместно, где используются абстракции. Вот несколько примеров:

  • Даже простой обход двумерного массива может выполняться с разной скоростью в зависимости от используемого направления обхода: вертикального или горизонтального. В одном из направлений будет значительно больше исключений вида «отказ страницы», а обработка таких исключений — медленное дело. Программисты на ассемблере думают, что у них есть большое и плоское адресное пространство. Но на самом деле используется виртуальная память, абстракция, которая протекает каждый раз, когда происходит отказ страницы, и необходимо тратить дополнительные несколько наносекунд на подгрузку запрашиваемой страницы.
  • Язык SQL абстрагирует от процедурных шагов, необходимых для извлечения информации из базы данных. Вы указываете, что нужно извлечь, а база данных решает, как это сделать. Но в ряде случаев некоторые запросы на некоторых SQL-серверах в тысячи раз медленнее, чем их логические эквиваленты. Широко известен пример, когда запрос «where a=b and b=c and a=c» выполняется быстрее, чем «where a=b and b=c» на одном и том же наборе данных. В идеале, о таких деталях должна беспокоиться только спецификация, а не вы. Но иногда в абстракции находится дыра, которая вызывает просадку по производительности. Это заставляет вас разобраться с анализатором запросов, а затем понять, что пошло не так и как это исправить.
  • Сетевые библиотеки типа NFS и SMB позволяют работать с файлами на удаленных машинах, как с локальными файлами. Однако в некоторых случаях на нестабильном соединении файлы перестают вести себя как локальные, а вам как программисту приходится решать эту проблему. Это дыра в абстракции «удаленный файл то же самое, что и локальный файл”. А вот конкретный пример для системных администраторов. Если вы размещаете домашние каталоги пользователей на сетевом диске (одна абстракция), а пользователь создает .forward файл для переадресации своих писем (еще одна абстракция), то при недоступности сетевого диска файл .forward не будет найден и письмо не будет переадресовано. В итоге дыра в абстракции приведет к тому, что несколько писем будут выброшены на пол.
  • Предполагается, что строковые классы в С++ позволяют вам использовать строки как объекты первого класса. Они пытаются абстрагировать факт, что строковые манипуляции сложные, и позволяют вам работать со строками, как с числами. Почти все строковые классы в С++ перегружают оператор +, так что вы можете писать s + “bar” для конкатенации строк. Но знаете что? Вне зависимости от того, как сильно они стараются, во всем мире не существует ни одного класса, который позволил бы написать “foo” + “bar”, потому что строки в С++ всегда типа char*. В абстракции возникает дыра, и язык не позволяет вам ее залатать. (Забавно, но история эволюции С++ со временем может быть описана как история заделывания дыр в абстракции строк. Почему нельзя было добавить нативный строковый тип — мне до сих пор не ясно.)
  • И более того, вы не можете быстро ездить в дождливую погоду, даже если ваша машина оборудована крышей, дворниками, фарами и обогревателем, которые защищают вас от непогоды. Вам все равно придется беспокоиться о гидропланировании. А иногда дальность видимости заметно снижается, и вам приходится снижать скорость, потому что полностью абстрагироваться от погоды не получается. Закон дырявых абстракций в действии.

Из закона дырявых абстракций следует, что абстракции не упрощают нашу жизнь настолько, насколько нам хотелось бы. Когда я преподаю С++, мне хотелось бы избежать рассказа про тип данных char* и арифметику указателей. Было бы замечательно рассказывать сразу про STL, но однажды ученики напишут “foo” + “bar” и испугаются, а мне придется рассказать про char*. Или когда-нибудь они попробуют вызывать функцию Windows API с аргументом OUT LPTSTR, и им все равно придется узнать про char, указатели, юникод и wchar_t, а так же TCHAR и все, что просачивается через абстракцию.

При программировании с COM (Component Object Model — прим.пер.) было бы неплохо изучать сразу помощников Visual Studio и всю магию кодогенерации. Но если хоть что-то пойдет не так, то у программистов не будет ни малейшей идеи, что произошло, где искать ошибку и как ее починить. И мне придется рассказывать про IUnknown, CLSID и ProgIDS и… О, человечество!

При обучении ASP.NET было бы прекрасно обучать нажимать дважды по объектам и писать код, который будет выполняться на сервере, когда пользователь будет нажимать на объект. В сущности, ASP.NET устраняет разницу между обработкой нажатия на гиперссылку (тег <a>) и обработкой нажатия на кнопку. Но вот проблема: в HTML нельзя отправить форму нажатием на гиперссылку и разработчикам ASP.NET нужно было спрятать эту проблему. Они решили проблему генерацией нескольких строк JavaScript-кода в onclick-обработчике гиперссылки. Но, тем не менее, это дыра в абстракции. Если у конечного пользователя будет отключен JavaScript, то ASP.NET будет работать некорректно, а программист приложения без осознания, что именно абстрагирует ASP.NET, не сможет понять, что произошло.

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

Это парадоксально, но с каждым разом, когда мы изобретаем все более высокоуровневые инструменты с более качественными абстракциями, становиться профессиональным программистом все сложнее.

В ходе своей первой стажировки в Microsoft я разрабатывал библиотеки для работы со строками на Macintosh. Вот пример типичного задания: написать версию strcat, которая возвращает указатель на конец новой строки. Всего несколько строк кода на Си. Все, что я делал, было прямиком из K&R (Керниган и Ритчи — прим. пер.) — одной тонкой книги про язык программирования С.

А после я устраиваюсь в CityDesk (компания закрылась в 2016 году — прим.пер.). Теперь мне необходимо знать Visual Basic, COM, ATL, C++, InnoSetup, внутреннюю организацию Internet Explorer, регулярные выражения, DOM, HTML, CSS и XML. Это все инструменты высокого уровня по сравнению с вещами из K&R, однако я все еще должен знать все вещи из K&R.

Десять лет назад мы могли представлять, что новые парадигмы программирования упростят нам разработку сейчас. На самом деле, абстракции, которые мы создали за эти десятилетия, позволяют нам легко ладить с новыми уровнями сложности, которые нам не поддавались 10-15 лет назад, как в случае с разработкой графических интерфейсов или работы с сетью. А сейчас у нас есть множество замечательных инструментов, таких как объектно-ориентированные языки с поддержкой форм, которые позволяют нам выполнять работу невероятно быстро. Пока однажды мы не столкнемся с проблемой, где абстракция «протекает», и нам потребуется две недели на решение. Когда вам нужно нанять программиста на Visual Basic, чтобы делать только VB-код, это не самая лучшая затея. Потому что такой программист будет застревать каждый раз, когда наткнется на дыру в абстракции Visual Basic.

Закон дырявых абстракций тянет нас на дно.

 

Эта статья является переводом.
Оригинал:
The Law of Leaky Abstractions by Joel Spolsky

Что такое абстракция? — Определение с сайта WhatIs.

com От

Абстракция (от латинского abs , что означает от и Trahere , что означает для рисования ) — это процесс удаления или удаления характеристик из чего-либо, чтобы свести это к набору основных характеристик. В объектно-ориентированном программировании абстракция является одним из трех основных принципов (наряду с инкапсуляцией и наследованием).В процессе абстракции программист скрывает все, кроме релевантных данных об объекте, чтобы уменьшить сложность и повысить эффективность. Точно так же, как абстракция иногда работает в искусстве, объект, который остается, является представлением оригинала с опущенными нежелательными деталями. Сам результирующий объект может называться абстракцией, что означает именованный объект, состоящий из выбранных атрибутов и поведения, специфичных для конкретного использования исходного объекта .Абстракция связана как с инкапсуляцией, так и с сокрытием данных.

В процессе абстракции программист пытается гарантировать, что имя объекта будет иметь смысл, и что в него будут включены все соответствующие аспекты, а не посторонние. Реальная аналогия абстракции может работать следующим образом: вы (объект) устраиваете свидание вслепую и решаете, что им сказать, чтобы они узнали вас в ресторане. Вы решаете включить информацию о том, где вы будете жить, ваш рост, цвет волос и цвет вашей куртки.Это все данные, которые помогут процессу (ваше свидание вас найдет) пройти гладко. Вы должны включить всю эту информацию. С другой стороны, есть много информации о вас, которая не имеет отношения к данной ситуации: ваш номер социального страхования, ваше восхищение малоизвестными фильмами и то, что вы «показывали и рассказывали» в пятом классе, — все это не имеют отношения к этой конкретной ситуации, потому что они не помогут вашему свиданию найти вас. Однако, поскольку сущности могут иметь любое количество абстракций, вы можете использовать их в другой процедуре в будущем.

Последнее обновление: июнь 2014 г.

Продолжить чтение об абстракции

Как сделать ваш код более читабельным с помощью абстракции

by Tiago Antunes

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

В этой статье я объясню вам концепцию абстракции и ее использование, а также приведу несколько примеров на Python.

Перво-наперво: что такое абстракция?

Согласно моему учителю по основам программирования:

«Абстракция — это упрощенная спецификация объекта».

Это означает, что абстракция — это представление вычислительного объекта. Это способ скрыть конкретную информацию и предоставить программисту только самую важную информацию.

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

Давайте взглянем на дерево двоичного поиска (если вы не знаете, что они собой представляют, ознакомьтесь с моей статьей о них). Мы можем определить узел как объект со следующими свойствами:

  Узел имеет: Узел * левый узел * справа int val  

Здесь мы бы сказали, что узел имеет два указателя на другие узлы и значение int. Но , насколько полезен для кого-то по сравнению с функцией insert (node, value) , и она просто правильно вставила бы ее? Таким образом, вам просто нужно было его вызвать, и все было сделано.Простой.

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

Хорошо, но насколько хороша абстракция данных?

Абстракция данных позволяет нам преобразовывать сложную структуру данных в простую и удобную в использовании. Результатом этого является то, что программа с высоким уровнем сложности кода может быть преобразована в программу, которая выглядит близко к английской (назовем ее высокоуровневым кодом ).

Тип данных состоит из двух частей: свойств и методов, которые могут быть общедоступными или частными. Публичные — единственный способ использовать данные. Они должны охватывать все функции, которые вы хотите, чтобы данные могли выполнять.

Что происходит, если вы используете свой абстрактный код? На самом деле не имеет значения, изменятся ли ваши внутренние свойства, если методы по-прежнему получают те же аргументы и делают то же самое, что и раньше. Если что-то не так, поменять нужно только один раз.

Давайте возьмем пример и поработаем с ним: Векторы

Предположим, что это векторы:

  • Объекты с 2 значениями, x и y
  • x и y являются неотрицательными числами

Таким образом, Векторы что-то вроде (2, 5), (0, 19) и т. д.

Хороший способ создания абстракций — использовать объекты. Они обеспечивают сокрытие информации и анонимность представления. Это позволяет пользователю сохранить абстракцию.

Начнем с определения нашего класса (я не буду определять проверку типа, чтобы код был более чистым, но вы должны это сделать):

Итак, мы определили несколько методов, и теперь у нас есть много вещей, которые мы можем сделать:

Для 2D-вектора это может показаться простым. Если вы начнете реализовывать это в более крупных и сложных программах, вы заметите, что они действительно пригодятся.

Давайте теперь сделаем другую реализацию вектора класса (изменим его внутреннее состояние) на что-то с теми же методами, но с другим кодом:

Реализация другая, но результат тот же

Если мы запустим те же команды, вывод останется прежним. Это из-за используемой нами абстракции, даже если код полностью изменился. Вот почему так важно использовать абстракцию.Это обеспечивает гибкость вашего кода и независимость от кода других людей.

Давайте теперь рассмотрим другой пример, на этот раз с двумя классами: City и Citizen.

Город состоит из граждан

И мы получаем следующее:

  ### ВЫВОД ### Население города - 1000, случайное: гражданин - женщина 20 лет Население города - 1000, случайное: гражданин - мужчина 74 лет old  

Но теперь представьте, что мы хотим изменить то, как класс Citizen работает внутри. Если бы мы не использовали абстракцию, нам пришлось бы менять весь код! Это много работы!

Теперь мы очень быстро изменили класс Citizen — и все по-прежнему работает!

Теперь, если код запускается снова, мы знаем, что он работает, хотя результаты другие. Как видите, мы поменяли целый класс, но все работает!

Заключение

На первый взгляд может показаться, что абстракция не нужна. Чем ниже уровень языка, который вы используете, тем важнее использовать абстракцию. Это позволяет избежать сложного кода и действительно упрощает все. В таких языках, как C, это действительно полезно. Если вы сомневаетесь в этом, посмотрите этот созданный мной проект, в котором я реализовал абстракцию, и было действительно легко понять, что происходит.

Если у вас есть какие-либо вопросы или что-то, о чем вы хотите поговорить или обсудить, оставьте комментарий ниже!

Не забудьте подписаться на меня в Instagram и Twitter!

Определение абстракции

Домашняя страница: Технические термины: Определение абстракции

Абстракция — это общее понятие или идея, а не что-то конкретное или осязаемое.В информатике абстракция имеет аналогичное определение. Это упрощенная версия чего-то технического, например функции или объекта в программе. Цель «абстрагирования» данных — снизить сложность за счет удаления ненужной информации.

На определенном уровне мы все думаем о компьютерах абстрактно. Когда мы печатаем документ в текстовом редакторе, мы не думаем о ЦП, обрабатывающем каждую вводимую букву и о сохранении данных в памяти. Когда мы просматриваем веб-страницу, мы не думаем о двоичных данных, которые передаются через Интернет, обрабатываются и отображаются веб-браузером.Мы просто печатаем наши документы и просматриваем Интернет. Таким образом мы естественным образом абстрагируем компьютерные концепции.

Даже высокотехнологичные люди, например разработчики программного обеспечения, могут извлечь выгоду из абстракции. Например, одним из ключевых преимуществ объектно-ориентированного программирования является абстракция данных. Он преобразует сложные объекты в упрощенные объекты, к которым можно получить доступ и изменить в программе. Эти объекты, которые часто называют классами, могут иметь несколько атрибутов и методов. Объединяя эти элементы в один объект, программистам становится проще получать доступ к данным и управлять ими в программе.

Обновлено: 19 апреля 2019 г.

https://techterms.com/definition/abstraction

TechTerms — Компьютерный словарь технических терминов

Эта страница содержит техническое определение абстракции. Он объясняет в компьютерной терминологии, что означает абстракция, и является одним из многих технических терминов в словаре TechTerms.

Все определения на веб-сайте TechTerms составлены так, чтобы быть технически точными, но также простыми для понимания. Если вы найдете это определение абстракции полезным, вы можете сослаться на него, используя приведенные выше ссылки для цитирования.Если вы считаете, что термин следует обновить или добавить в словарь TechTerms, отправьте электронное письмо в TechTerms!

Подпишитесь на информационный бюллетень TechTerms, чтобы получать избранные термины и тесты прямо в свой почтовый ящик. Вы можете получать электронную почту ежедневно или еженедельно.

Подписаться

Что такое абстракция (информатика)?

Что означает абстракция?

Абстракция — фундаментальный принцип в некоторых типах информатики. Это ключевой аспект проектирования объектно-ориентированных языков программирования и интерфейсов прикладного программирования.Это также одна из наименее понятных идей в программировании, частично по семантическим причинам.

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

Techopedia объясняет абстракцию

Причина, по которой это сбивает многих людей с толку, заключается в том, что абстракция «не похожа» на то, что она есть семантически. Это похоже на то, чтобы сделать что-то более расплывчатое, потому что мы так используем это в общем языке.

Однако в информатике абстракция обычно означает упрощение и отделение сигнала от шума, чтобы сделать программирование более эффективным и действенным.

Объектно-ориентированное программирование

Код

В одном из наиболее ярких примеров абстракции информатики, в объектно-ориентированном программировании, абстракция часто работает посредством использования объектов в коде. Эти объекты, как переносимые контейнеры атрибутов и повторяющиеся структуры кода, представляют собой абстрактную функциональность, которая в противном случае могла бы быть запрограммирована линейным образом.

Другими словами, средство абстракции — это объекты в коде, которые берут целую кучу базового кода и делают его переносимым и повторяемым.

Класс

Другой конвейер абстракции в объектно-ориентированном программировании — это класс. Классы объектов дополнительно разделяют принцип повторяемости использования и автоматического распространения кода.

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

Вместо того, чтобы создавать виртуальный объект, такой как кофеварка, с нуля, программировать каждую строку его функциональности вручную, инженеры могут вместо этого вызвать объект «кофеварка» и подключить «зерна», «кофейные чашки» и т. Д., чтобы получить тот же результат с гораздо меньшими усилиями.

Фактически, абстракция, которая работает в объектно-ориентированном программировании, — это лучший способ показать, насколько мощно эти идеи поддерживают виртуальные «миры» — когда программисты могут создавать всевозможные виртуальные объекты со своими собственными атрибутами, они могут больше эффективно моделировать реальный мир, физический мир и в то же время оптимизировать эффективность рабочего времени программиста.

Обе эти замечательные возможности ООП принесла миру технологий.

Интерфейс прикладного программирования

Другой современный яркий пример абстракции проиллюстрирован в интерфейсе прикладного программирования (API), который так распространен в кроссплатформенных системах.

API — это ключевой способ предоставить эту информацию об абстракции, чтобы сторонним сторонним лицам не нужно было знать так много о внутренней кодовой базе. В очень простом смысле API-интерфейсы являются «соединителями» — стороны будут использовать API для подключения кода одного приложения к коду другого приложения, для проталкивания наборов данных через кросс-платформенную среду и обеспечения возможности совместной работы этих программ в автоматическом режиме

Таким образом, API функционирует как ключевое средство абстракции, встраивая те объектно-ориентированные принципы, которые показывают «внешней программе», что делает «внутренняя программа».

В заключение, абстракция — это просто процесс повышения универсальности информации кодовой базы за счет упрощения ее представления во внешних системах. Это, однако, привело к огромному техническому прогрессу, предшествовавшему другим видам изменений ядра, таким как переход к виртуализации сетей.

Объектно-ориентированное программирование что такое абстракция?

Пользователю не нужно знать сложность процесса приготовления кофе, ему достаточно просто вставить кофейные чалды и нажать кнопку.

Вы уже попали в точку. Абстракция заключается в удалении нерелевантных деталей реализации, чтобы сосредоточиться на соответствующих деталях. Это различие, которое вы описываете.

В реальном мире такие несущественные детали быстро переходят к молекулам, исследованиям химии, физики и т.д., когда все, что нас интересует, — это чашка кофе.

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

По сути, в программировании абстракция сводится к разделению интерфейса, который использует / видит клиент, и базовой реализации, обеспечивающей эти вещи, — что немного отличается от реального мира, поскольку мы манипулируем состоянием, а не молекулами. . Отделяя интерфейс от реализации, мы одновременно фокусируемся на релевантном (по мнению автора) и не фокусируемся на реализации.

Generalization — это рефакторинг, который позволяет одному интерфейсу работать в нескольких различных сценариях (например, при поиске точек соприкосновения между объектами разных типов).Это тесно связано с абстракцией, поскольку обобщение также фокусирует внимание на релевантном, удерживая при этом нерелевантное, хотя при этом особое внимание уделяется общему основанию и специализациям.

Инкапсуляция включает в себя внутренние детали чего-либо с целью ограничения / контроля / сокрытия того, как объект может взаимодействовать с внешним миром. Таким образом, инкапсуляция также скрывает детали реализации, фокусируясь на соответствующем интерфейсе для потребителя, но она несколько больше направлена ​​на предотвращение неправильного обновления / модификации / использования инкапсулированного объекта, а не на абстракции, сосредоточенные на интерфейсе.

Все они, возможно, перекрываются и объединяются в ООП.

Абстракция может быть выполнена с помощью одной функции, которая является своего рода интерфейсом (часто называемым сигнатурой в ООП), или группой связанных функций (часто называемой интерфейсом в ООП, также переходит к конструкции класса) или лесом интерфейсы / классы (часто делается с использованием пространства имен в ООП).

В некоторых языках это формальные конструкции, хотя эти подходы также могут быть реализованы на языках, которые не предлагают (одну или несколько) их в качестве формальных конструкций.

Обобщение относится к иерархии классов и интерфейсов, поскольку обычно у нас есть базовый класс или интерфейс, представляющий общую основу для нескольких концепций, а затем специализации (конкретные реализации интерфейсов или подклассы базовых классов), которые предлагают различие для этих концепции. Итак, абстракция на нескольких уровнях.

В то время как цель инкапсуляции состоит в том, чтобы способствовать правильному использованию и отрицать несоответствующее использование путем сокрытия информации и возможностей с использованием частных vs.общественность, например.

уровней абстракции в программировании: обзор — BMC Software

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

Что такое уровень абстракции?

Уровень абстракции разделяет две вещи. Для программирования это часто разделение задач на отдельные объекты.

Например, объекту A может быть назначена задача выборки изображения из базы данных и последующей обработки изображения при извлечении

Создание уровня абстракции разделит этот объект A на объекты A и B, где:

  • Сущность A извлекает ресурс.
  • Сущность B — теперь абстракция — зависит от изображения, которое нужно вернуть из первой операции, чтобы затем выполнить свою вторую операцию.

Уровень абстракции позволяет одной стороне или операции полностью отвечать за одну задачу, в то время как зависимый ожидает, пока эта сторона вернет данные для обработки.

(Источник)

Абстракция в коде

API — это уровни абстракции. Хотя API-интерфейсы служат многим целям, они используются следующим образом: разработчик пытается создать приложение, включающее твиты, поэтому они подключаются к новому APIv2 Twitter для получения данных твитов.

Разработчик не несет ответственности за создание службы, позволяющей пользователям общаться друг с другом с помощью сообщений длиной 140 символов. Сервис Twitter управляется Twitter, и вся ответственность за сбор их данных лежит на их плечах.

Разработчику достаточно получить данные и использовать их в своих целях. Поскольку разработчик не несет ответственности за получение данных и предоставление службы Twitter на их уровне работоспособности, API Twitter отделен от операций разработчика.

В нашем случае абстракцию тоже можно назвать косвенной. В известной цитате Дэвида Уиллера,

«Все проблемы в информатике могут быть решены с помощью другого уровня косвенного обращения».

Создать абстракцию так же просто, как заменить одну функцию на две. Эта функция Python открывает текстовый документ и подсчитывает количество строк, количество слов и количество содержащихся в нем символов.

 def processDoc (имя файла):
с open (filename, 'r') как f
number_of_lines = 0
number_of_words = 0
number_of_characters = 0
для строки в f:
линия = линия.полоса ("\ n")
слова = line.split ()
number_of_lines + = 1
number_of_words + = len (слова)
number_of_characters + = len (строка)
вернуть число_строков, число_слов, число_символов 

Чтобы создать уровень абстракции из этой функции, «подсчетная» часть функции может быть абстрагирована от «открывающей» части функции. Одна функция не отвечает за обе; две функции берут на себя ответственность за процесс:

  • Функция openDoc откроет документ и вернет документ в виде строки, которую может использовать компьютер.
  • Функция processDoc принимает в качестве входных данных строковый вывод функции openDoc, запускает некоторые сценарии подсчета и возвращает их значения.

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

 def openDoc (имя файла):
с open (filename, 'r') как f
текст = f.строки чтения
текст возврата

def processDoc (текст):
number_of_lines = 0
number_of_words = 0
number_of_characters = 0
для строки в тексте:
line = line.strip ("\ n")
слова = line.split ()
number_of_lines + = 1
number_of_words + = len (слова)
number_of_characters + = len (строка)
вернуть число_строков, число_слов, число_символов 

Уровни абстракции в разных доменах

Вы будете использовать уровни абстракции по-разному, в зависимости от области программирования.

Для внешнего программирования создание большего количества модульного кода означает создание большего количества уровней абстракции. Использование модульного кода в интерфейсных программах позволяет использовать код:

  • Возможность повторного использования
  • Долгосрочная устойчивость

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

Функции как услуга (FaaS), которые обычно представляют собой функции, завернутые в контейнер, — это функции, которые управляют уровнем абстракции вдали от основного кода.В приведенном выше примере кода показаны две функции, которые можно записать в два разных контейнера:

  • Одна из функций — это облачная функция, которая открывает файлы и возвращает из них текст.
  • Другой может быть облачной функцией, которая принимает строку в качестве входных данных и считает ее строки, слова и символы.

В Kubeflow, программном обеспечении машинного обучения Google с открытым исходным кодом, каждый шаг в конвейере представляет собой контейнер. Вместо того, чтобы запускать задание машинного обучения из одного скрипта Python, внутри одной записной книжки Jupyter или в одном контейнере, каждый шаг в файле преобразуется в функцию входов и выходов.Вся записная книжка доводится до абстракции и проходит через контейнеры. Используя встроенный метод Kubeflow, они предоставляют инструменты для преобразования функции в контейнер.

По своему замыслу, инфраструктура Kubernetes, способность маневрировать и запускать контейнеры в неизменяемой инфраструктуре, выступает за то, чтобы функции и процессы кода существовали на абстрактных уровнях.

Когда использовать слои абстракции

Слои абстракции не нужны начинающим программистам.Абстрактные слои играют роль скорее художественной формы — их можно использовать при обдумывании дизайна кода и для определения того, какие процессы происходят, когда и где, и какие процессы зависят друг от друга.

Дополнительные ресурсы

Дополнительную информацию можно найти на следующих ресурсах:

Эти публикации являются моими собственными и не обязательно отражают позицию, стратегию или мнение BMC.

Обнаружили ошибку или есть предложение? Сообщите нам об этом по электронной почте blogs @ bmc.com.

python — что означает абстракция в программировании?

Абстракция — это ключевая концепция всей информатики. Без абстракции мы бы все равно программировали машинным кодом или, что еще хуже, вообще не имели бы компьютеров. Так что ИМХО, это действительно хороший вопрос.

Что такое абстракция

Абстрагирование чего-то означает, что дает имена вещам, так что имя отражает суть того, что делает функция или вся программа.

Один пример приведен в книге, на которую вы ссылаетесь, где сказано:

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

Забудьте на мгновение о черепахах и просто подумайте о рисовании квадрата. Если я скажу вам нарисовать квадрат (на бумаге), вы сразу поймете, что делать:

  • нарисуйте квадрат => нарисуйте прямоугольник со всеми сторонами одинаковой длины.

Вы можете сделать это без лишних вопросов, потому что вы наизусть знаете, что такое квадрат , и я не буду рассказывать вам шаг за шагом. Здесь слово квадрат — это абстракция «нарисовать прямоугольник со всеми сторонами одинаковой длины».

Глубокие абстракции

Но подождите, как узнать, что такое прямоугольник ? Что ж, это еще одна абстракция для следующего:

  • прямоугольник => нарисуйте две параллельные друг другу линии одинаковой длины, а затем добавьте еще две параллельные линии, перпендикулярные двум другим линиям, опять же той же длины, но, возможно, другой длины, чем первые две.

Конечно, это продолжается и продолжается — линий , параллельных , перпендикулярных , соединяющих — все это абстракций хорошо известных концепций.

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

Реальная сила абстракции

Это первая сила абстракций : они значительно упрощают общение и работу.

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

  • дом => нарисуйте квадрат с треугольником поверх него

Далее вам нужна деревня:

  • деревня => нарисуйте несколько домов рядом друг с другом

Ой, подождите, мы хотим город — и у нас есть новая концепция улица :

  • город => нарисуйте несколько деревень рядом друг с другом, заполните пустые места более домов , но оставьте место для улиц
  • улица => (некоторое определение улицы)

и так далее…

Как все это применимо к программированию?

Если в процессе планирования вашей программы (процесс, известный как анализ и проектирование ), вы найдете хорошие абстракции к проблеме, которую пытаетесь решить, ваши программы станут короче, следовательно, их легче писать и — что, возможно, более важно — проще читать. Способ сделать это — попытаться понять основные концепции, которые определяют ваши проблемы — как в (упрощенном) примере рисования дома , это было квадратов и треугольников , чтобы нарисовать деревню было домов .

В программировании мы определяем абстракции как функции (и некоторые другие конструкции, такие как классы и модули, но давайте пока сосредоточимся на функциях). Функция , по сути, называет набор отдельных операторов, поэтому функция по сути является абстракцией — см. Примеры в вашей книге для подробностей.

Красота всего этого

В программировании абстракции могут как повысить производительность, так и снизить ее. Вот почему часто часто используемые функции собираются в библиотек , которые могут быть повторно использованы другими.Это означает, что вам не нужно беспокоиться о деталях, вам нужно только понимать, как использовать готовые абстракции. Очевидно, это должно упростить вам задачу, чтобы вы могли работать быстрее и, следовательно, быть более продуктивным:

Пример :

Представьте, что есть графическая библиотека под названием «nicepic», которая содержит предопределенные функции для всех обсуждаемых выше абстракций: прямоугольники, квадраты, треугольники, дом, деревня.

Допустим, вы хотите создать программу на основе приведенных выше абстракций, которая рисует красивую картину дома, все, что вам нужно написать, это:

  импорт nicepic
draw_house ()
  

Итак, это всего лишь две строчки кода, чтобы получить что-то более сложное.Разве это не прекрасно?

Надеюсь, это поможет.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *