All streams
Search
Write a publication
Pull to refresh
24
1.3
Костромин Кирилл @SadOcean

User

Send message
Да, но это работает если знаешь что писать.
А без знания нужно либо перерывать подсказки в поисках нужной — это работает в целом с методами разве что, но не с типами/интерфейсами
ИИ тут поможет разве что с демонстрацией (что его схема детерминирована)
В остальном — кажется, что независимо от того, можно ли создать сильный ИИ, человеческое сознание детерменировано. Другое дело, что у него высокая сложность и оно завязано на множество факторов окружающей среды, включая биохимию собственной тушки. Все эти штуки не получится воспроизвести идеально, чтобы проверить, действительно ли оно детерменировано.
Да, разумеется, поэтому, несмотря на то, что рынок смартфонов они слили, чувствуют они себя очень хорошо.
Потому что десктоп работает, оффис работает, а, главное (и неочевидное) — облака работают
Когда то было сложно представить, что должно случиться Amiga, чтобы они потеряли лидерство.
Что должно случиться с Nokia, чтобы она потеряла лидерство.
Что должно случиться с microsoft, чтобы windows mobile потеряла лидерство…
Ну мы же обсуждаем потенциальную жизнь с Земли — у всей жизни (и у вирусов) есть генетическая информация. Другой просто нет.
Ну у простейших не ДНК, а РНК, но это ведь тоже «гены» в классическом смысле.
Кстати, есть еще прикольный вариант, что бактерии, с Земли, но не с Венеры, а доставленные другим способом.
Например, каким нибудь камнем из верхних слоев атмосферы Земли в атмосферу Венеры.
История у нас длинная, почему бы преценденту не случиться.
Ведь рассматривают вариант, что жизнь зародилась не на Земле, а была занесена из космоса — теоретически бактерии могут преодолевать космические расстояния.
Тогда, возможно, при помощи генетического анализа определить, насколько они для нас родственны и когда отделились от земной жизни.
Возможно, но думаю, что ребята знают, о чем говорят.
Физика то у нас одна, порядки величин определить можно, исторические примеры есть. Например, заполнение атмосферы Земли кислородом или осаждение железа в оксиды в океане.
Бактерии, конечно, молодцы, но не всемогущи.
Это был бы эпичный просто пример.
Занесли жизнь на другую планету и она там в подходящих условиях эпически размножилась.
Но, к сожалению, астрономы упоминали, что это маловероятно — видимо не хватило бы времени на воспроизводство такого количества.
Статья интересная и занимательная, но очень сумбурная.
Автор прыгает по разным уровням детализации, где то объясняет подробно, где то — поверхностно, а где то — детали, которые очень тяжело разобрать.
Но в целом спасибо, мне понравилось
Можно легко показать на примерах, как может появляться такой код и почему поддерживать его правильно сложно.

1. К примеру, у тебя есть класс А, который использует класс B
Все отлично

2. Приходит новая задача — класс А должен уметь иногда вместо класса B использовать класс С
Ты пишешь if по параметру, вставляешь класс C — задача решена
Все отлично (правда отлично, если бы история закончилась тут — ты был бы молодцом, твой код был бы хорошим, тобой были бы довольны начальник, жена, мама и бабушка)

3. Приходит новая задача — класс А, иногда должен уметь вместо B и C использовать класс D. И в этом случае еще по другому надо обрабатывать часть класса А.
И тут у тебя выбор:
3.1 — Написать еще пару if и воткнуть класс D в пару мест — быстро и просто (хотя может уже не столь идеально)
3.2 — Понять, что класс D, как B и C имеет общие детали работы, и их можно обобщить, частично унифицировать, а часть функциональности вынести в Z. Будет гораздо лучше лучше, чем п3.1, и лишь чуть сложнее, чем в п.1 начале
Но потребует переписывать и класс A, и класс B и класс C, а они уже написаны и протестированы, на это потребуется больше времени, чем п3.1. Начальство негодует.

Уже тут у тебя есть выбор, каким молодцом быть. В одних случаях недоволен будет начальник, в других — бабушка (хороший же мальчик!).

4 А ведь проект развивается!
4.1 Естественно, приходят еще добавления новых режимов обработки E(/F/G/ ?)…
И если ты выбрал 3.2 — то тебе нормально, а вот если 3.1 — то опять нужно решать, либо ты плодишь if-ы, делая код менее читаемым, либо менять нужно уже ABCD/
4.2 Естественно, новые режимы E(/F/G/ ?) не нужны и не приходят к тебе никогда. Тогда, выбрав 3.1 ты на самом деле молодец, а в следующем обновлении вы выкинете класс А целиком и напишите другой, более красивый.

И в общем заранее не угадаешь.

1.1, ретроспективный пункт
Ты — умелый и опытный программист, который осознает, что для задачи A + B, наверняка потребуются C/D/E
Сроки не давят, можно попробовать предусмотреть разумные точки расширения (YAGNI будет не прав, если тебе это понадобится). Поэтому ты делаешь 3.2 сразу. Да, немножко оверинженеринг, и времени для красоты заняло больше. Непонятно, окупится ли. Но если появятся C/D/E — будет меньше боли.

1.1.1 — приходит коллега и не понимает, зачем тут метод с одним аргументом.
Когда читаешь несколько разных книг (особенно противоречивых) и сравниваешь с собственным опытом — получается весьма полезно. Главное не воспринимать как истину в последней инстанции.
Мне в этом смысле нравится не столько «что делать», но описание «почему мы пришли к выводу, что так нужно делать, какую проблему это решало» — самые ценные книги как раз содержат примеры кейсов, и если их анализировать, можно понять, какие вещи и почему тебе не подходят или нужно адаптировать.
Если универсальных рецептов нет — неуниверсальные очень неплохи
Главное без фанатизма.
К сожалению «где остановиться?» — это самый важный вопрос тут. Это традиционная проблема со многими рекомендациями по программированию — доведение до абсурда.

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

def onWindowShown(self):
    // show canvas
    self.canvas.showRect(widht, height);
    self.canvas.setColor(back_color);
    // set controls state
    self.start_button.setActive(player.isReady())
    self.exit_button.setActive(!player.IsTutorialStarted())
    // spawn effect
    self.stars_effector.SpawnStars(self.start_button.position)

Представьте, что этого кода в 2 раза больше, а с развитием проекта этот код легко может вырасти в 4 раза (больше эффектов, сложнее логика)
Он станет значительно лучше, если абстрагировать операции

def onWindowShown(self):
    self.showBackground(widht, height, back_color);
    self.setControlsState(player.isReady(), !player.IsTutorialStarted())
    self.showStartEffects()


Второй момент — сложные сравнения, тут даже пример с одной строчкой можно
// вместо
if (user.account.balance > 0 and user.payment_mode != 0 and !user.account.isBanned):
   doIt()

// сделать 
if (user.ReadyToPay()):
   doIt()

Тут имеется смысл, потому что неявный набор сравнений теперь поименован

Третий вариант (как в вашем примере) — абстрагирование для других абстракций
Ваш пример
def reset_label(cls):
    """
    reset intenal counter
    """
    cls.last_label = 0

Выглядит глупым (возможно так и есть), но представьте, что у вас есть экран, и потребители используют у него только методы
set_label(cls)
и
reset_label(cls)
set_label оправдан — он сложный, и устанавливает у cls множество разных флажков и примочек, помимо текстового значения.
в таком случае reset_label правильно сделать именно так — иначе получится, что включаешь ты через метод, а выключаешь — через ж*пу
Еще вариант — метод reset содержал еще инструкции и был оправдан, но они умерли с изменением проекта
Но скорее всего просто абстракция ради абстракции случайно получилась)
Есть такая рекомендация — switch для одной цели должен быть в одном месте.
Если нужно при добавлении нового элемента добавлять его обработку в разные методы — возможно вы неправильно декомпозировали задачу и нужно превратить элемент в интерфейс, который будет иметь реализации для разных типов
Тогда останется только один свич — при создании типа объектов
Это зависит от процесса
Если ты — и геймдизайнер и программист и в коде хранишь уровни (простой и надежный вариант для таких простых игр, кстати), то удобно хранить как раз символы по строкам, потому что визуально видны уровни.
Казуальный Wysiwyg эдакий
Так хранить же (чтобы уровни задавать и паттерны), а обрабатывать можно и в массивах
Разумеется
Но для понимания некоторых черных ящиков полезно понимать, на каких костылях они стоят.
Если учить от обратного (с высокоуровневых вещей), такого понимания не будет и магия будет больше магией.
На процедурных языках программирования можно легко писать в ООП стиле.
Собственно части Линукса так написаны — на С, но в процедурной парадигме, с оформленными специально объектами (структуры + обрабатывающие их методы).
И С++ изначально был просто препроцессором для С, то есть по факту сахаром, который спокойно переводился в С код.
Инкапсуляция — сахар. Просто синтаксис для удобного связывания, и организации.
Области видимости — сахар. Аналог наследование может быть достигнут включениями или побайтовым совпадением структур (чтобы их подкладывать)
И только аналоги интерфейсов и виртуальных методов для полиморфизма реализуются сравнительно тяжело, с помощью ссылок на ссылки на функции и в этом духе.
ООП — реально про организацию кода и ООП языки — просто специально адаптированные под нужный сахар.
Так то мое ИМХО, что rust и go — вполне себе ООП френдли, потому что единственное, чего там нет, это наследования реализации (от которых и так рекомендуют отказываться все кому не лень), все остальные пункты — вполне.
Это объяснение, что принцип такой, я не предлагаю так делать.
Абстрактно можно считать методы — простыми функциями, в которые вместе с параметрами передается ссылка на объект, от имени которого вызывается объект.
То есть вообще — речь о том, что ООП — это просто абстракция, сахар, нужная для организации. После компиляции по факту он превращается в обычный процедурный код. Соответственно ООП может быть сэмитирована через обычный процедурный код (привет С++ и линукс, написанный на С в объектном стиле)
Область видимости — такой же сахар, нужный чтобы ограничить программиста в использовании класса. Оно работает только до компиляции, чтобы сообщить «автор класса дал тебе публичный интерфейс — пользуйся им, чтобы работать с объектом безопасно». Приватные переменные — внутреннее состояние объекта, которое изолируется и защищается.
Это позволяет собственно делать самое полезное, что есть в ООП — разбивать код на понятные блоки, каждый из которых на своем уровне работает с простыми снаружи кусочками, сложными внутри.

Кстати статическому классу доступны приватные поля его класса через ссылку:
    class Program
    {
        static void Main(string[] args)
        {
            var a = new A();
            a.DoIt(1);
            A.DoItStatic(a, 2);
        }
    }

    public class A {
        private int b = 1;

        public void DoIt(int c) {
            b = c;
            Console.WriteLine(b);
        }

        public static void DoItStatic(A @this, int c) {
            @this.b = c;
            Console.WriteLine(@this.b);
        }
    }

Вот так работает

Information

Rating
1,489-th
Location
Ставрополь, Ставропольский край, Россия
Date of birth
Registered
Activity