Ответы пользователя по тегу Программирование
  • Что такое "call back interface"?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Если речь о Java и интерфейсах, то пример - как-то так:

    interface IObserver {
      void notify(Event e); //I'm a callback  ;)
      ...
    }
    
    interface IObservable {
      void register(IObserver o);
      void unregister(IObserver o);
      ...
    }


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

    В простейшем случае экземпляр класса, имплементирующего этот интерфейс (наблюдатель) сначала должен зарегистрироваться у какого-нибудь экземпляра, имплементирующего второй (наблюдаемого). После этого, всякий раз, когда в наблюдаемом будет происходить что-то, интересующее наблюдателя, наблюдаемое будет вызывать метод notify() экземпляра наблюдателя (и, например, передавать в него информацию о произошедших изменениях, в виде Event... но это - уже частности, не существенные для понимания сути callback). И так - до тех пор, пока наблюдатель не "попрощается" с наблюдаемым, вызвав его метод unregister(). Кроме того, кто именно "познакомит" одного с другим, тоже не существенно: это может быть сам наблюдатель, или кто-то еще (например, какая-нибудь фабрика, брокер, менеджер и т.д.) Если говорить о "свойствах интерфейса", то суть паттерна состоит в договоренности: "я знаю, что у тебя есть метод, который я могу и буду вызывать, когда сочту нужным, и ты будешь знать, что этот вызов означает". Все остальное (в каком потоке вызывать, что конкретно должен делать этот метод и т.д.) обычно тоже регламентируется, но это, опять же, уже частности.

    Для сравнения и отграничения понятия callback (от банальной инкапсуляции и IoC) можно привести пример
    java.lang.Comparable<T> {
      int compareTo(T o);
    }

    Все, что обещает этот интерфейс/метод: "если ты меня вызовешь и передашь мне ссылку на экземпляр такого же класса, как я сам, я сравню себя (по некоему, только мне известному алгоритму) с этим экземпляром и верну результат". Кто его будет вызывать, когда, зачем, что он станет делать с результатом... все это самому имплементирующему классу не важно. Это, хотя и очень похоже, но, строго говоря, не укладывается в понятие callback, т.к. вызываемому методу и всему экземпляру класса, в общем, нет никакого дела до того а. кто его вызовет и б. что это будет означать. А понятие callback подразумевает, что предоставляющий этот метод класс а. знает, кто и зачем его вызовет и б. непосредственно заинтересован в этом.

    Ну и, для полноты картины, нужно также упомянуть, что в разных язакых есть много разных способов организации callback. В C# есть делегаты и события, в C можно передать указатель на функцию и т.д. В Java для этого удобно пользоваться интерфейсами. Но это ничего не меняет в самом понятии callback, заключаюшемся в том, что кто-то осознанно предоставляет другому определенный метод, а этот другой этот метод вызывает, и оба знают, что означает сам факт вызова.
    Ответ написан
  • Как правильно выбрать путь изучения?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Вам нужно для начала точнее определиться с собственными целями... Если цель пока просто поиграться с железом, чтоб понять, нравится или нет, то самое правильное будет спокойно продолжить получать фундаментальное образование по программированию и делать какие-нибудь DIY проекты. Если же уже понятно, что это "дело всей жизни", то придется еще много чего учить, чего на телематике наверняка не будет (по крайней мере, в нужном объеме) и без чего в низкоуровневом программировании и, особенно, робототехнике делать просто нечего. Это прежде всего физика, электротехника, схемотехника, общие принципы конструирования и разработки систем, плюс, разумеется, технологии производства (тупо уметь паять), измерений (тупо уметь пользоваться осцилографом или LA), стандартизация и т.д. и т.п. вплоть до того же всеми горячо любимого сопромата. Из программирования и математики помимо чисто фундаментальных знаний (типа алгоритмов и структур данных, которые можно учить на любом языке) тоже понадобится много конкретного, например, DSP, криптография, ассемблер, устройство компиляторов, протоколы... английский (как минимум "технический") тут даже смешно упоминать. Одним словом, будьте готовы к тому, что в таком случае Вам фактически понадобятся ДВА образования.

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

    А вот про "всю жизнь писать код" реально улыбнуло... Как только почувствуете, что устали писать код, паять, измерять, конструировать и, главное, изучать новое - так сразу же и уходите из профессии, ибо дальше в ней делать просто нечего! :)
    Ответ написан
  • Цикл с таймаутом ровно в 1 секунду?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Ваш вопрос можно приводить в качестве наглядного пособия на тему "Как именно вылазит боком кривая архитектура системы" :) Основная проблема в том, что интеграция компонент через storage есть зло, рано или поздно (чаще - рано) заставляющее разработчика выполнять стойку на ушах. Так что, если есть такая возможность, постарайтесь устранить зло в корне, т.е. найти способ узнавать об изменениях, ну, или хотя бы о самом факте, до того, а не после. Тогда не придется ничего опрашивать в цикле, а только реагировать на изменения. А это уже - половина проблемы!

    Если возможности нет, а делать все равно надо, сначала смитритесь с тем, что Вы никогда на PHP не добьетесь ровненько 86400 вызовов в сутки каждую секунду, если только не поставите ядро реального времени / не напишете соответствующий код на С и т.д. и т.п. Особенно, если storage крутится на том же процессоре в той же ОС, и количесво данных в нем будет со временем увеличиваться. Но это почти наверняка и не нужно, а нужно проанализировать задачу и понять, что на самом деле критично и какие отклонения от идеала возможны без ущерба для функциональности.

    "Примерно 0.03с" само по себе еще не о чем не говорит. Это всегда или в случае, если изменений нет, или если они небольшого объема? А если 90% данных обновились? Это - раз. Два: если изменения обнаружены, сколько может занять их обработка (в худшем случае)?.. И, наконец, три: если уже наступила "следующая секунда", а мы все еще не закончили обработку прошлых изменений, возникает целый ряд вопросов. Имеет ли в этом случае вообще смысл проверять новые изменения (сможем ли мы их осмысленно обработать, если найдем)? Если да, понадобится как минимум 2 потока. Если нет, насколько критично пропустить эту секунду? А сколько еще можно пропустить без ущерба для функционала? Предположим, это не критично, и мы уже пропустили секунду (или несколько), что нам важнее: чтоб следующая проверка выполнилась как можно ближе к границе "следующей секунды", или как можно быстрее? И т.д. и т.п.

    Не зная ответов на эти и подобные вопросы, невозможно предложить "правильное" решение. Но в качестве сферического коня в вакууме можно посоветовать бесконечный цикл, в котором выполняется проверка, реакция на найденные изменения, после чего вычисляется время до следующей проверки, на которое выполняется sleep().
    Ответ написан
  • Суть виртуальной машины Java?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Тут дали уже много хороших и правильных ответов, но хотелось бы уточнить, что вот эта метафора:
    Виртуальня машина java это тоже интерпретатор по сути

    может направить по весьма ложному пути!

    У слов в названиях есть достаточно точный смысл, и JVM называется именно машиной, а не интерпретатором, и не компилятором совершенно не случайно. Компилятор в Яве есть (javac), и он нужен не для выполнения программы, а именно для ее компиляции (в байткод). Имено поэтому он не входит в состав JRE (среды выполнения), а содержится в JDK (среде разработки). В самой JVM есть еще один, JIT-компилятор, который компилирует байткод в инструкции процессора во время выполнения программы, но это уже другая история, и его тоже никак не назвать интерпретатором.

    По сути JVM - это процессор, только виртуальный. И как у любого процессора (железного, типа x86, или виртуального, типа CLR в .NET), у него есть свой набор опкодов, называемый байткодом. Так же точно, как на х86 может выполняться код, порожденный компилятором с C++, или Pascal, или Go, так же и на JVM может выполняться байткод, скомпилированный из Java, или Scala, или Kotlin (или даже написанный вручную), а .class -файл, это, по сути, тот же .exe (точнее .so), скомпилированный под "процессор JVM". В этом и заключается кроссплатформенность. Так же, как код, скомпилированный под х86 будет выполняться на процессоре от Intel или AMD, так же и байткод JVM будет выполняться на JVM от Oracle, IBM, OpenJDK и т.д. И даже наличие JIT, компилирующего байткод в опкод конкретного железного процессора во время выполнения, все еще не дает повода обзывать честную стековую (SUN) или регистровую (Dalvik) VM интерпретатором, пусть даже и по сути :)

    Дело в том, что сама эта классификация (интерпретируемый/компилируемый ЯЗЫК) последние лет эдак 25 уже практически лишена смысла. Языкам, изначально ориентированным на реализацию в виде интерпретатора (с просто анализируемой лексикой, чтоб интерпретатор был поменьше и мог оставить самой программе достаточно места в ограниченной по объему памяти) типа APL или BASIC, сейчас (кроме, разумеется, очень узкоспециального применения) почетное место разве что в старых учебниках, из которых эту самую классификацию, с достойным лучшего применения упорством, продолжают дословно переписывать в новые. При этом, почему-то, забывают уточнить, что эти два понятия уже давно не про сами языки, а всего лишь про некоторые методы их реализации, и что с тех пор помимо этих методов появилось еще много других хороших и разных концепций на эту тему (типа VM, JIT, сборщиков мусора, да и хотя бы тех же OOП, разных видов типизации и еще миллион чего), которых в тех учебниках еще просто не было в силу их года издания. И что на сегодня уже даже для языков, принципиально заточеных для компиляции под регистровую архитектуру, типа С, есть пруд пруди интерпретаторов (раз, два, три)... которые, опять же, никто не называет виртуальными машинами, т.к. это все суть разные понятия. Короче, это все равно что пытаться понять, где в квантовой механике огонь, вода, земля и воздух, в том виде, как их понимали Платон и Аристотель :)

    P.S. Чтоб осознать, когда эта классификация еще была актуальна, рекомендую вот это . Там создатели APL, одного из первых настоящих интерпретируемых языков, обсуждают насущные проблемы языкостроения того времени. Если туго с английским, посмотрите хотя бы вступление... в тех железяках было меньше памяти и вычислительной мощности, чем в современной симке :)
    Ответ написан
  • Визуальное программирование для Джавы?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Существует, но не для Явы. Например, LabView. Там графический язык, на котором можно "написать" (нарисовать) программу, и увидеть её логику. А Ява - язык императивный, и визуализировать его, все равно, что пытаться заставить парусник ездить по железной дороге... теоретически - возможно, практически - довольно бессмысленно. Но если все равно очень хочется, то да... UML в помошь .
    Ответ написан
  • Как реализовать симуляцию JAVA используя многопоточность?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    По заявкам телезрителей :)
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    
    public class Simulation {
    
    	private static final Random globalRandom = new Random(System.currentTimeMillis());
    	
    	public synchronized int getRandomIntInRangeEnclosed(int min, int max){
    		return globalRandom.nextInt((max - min + 1) + min);
    	}
    	
    	private final static int CUSTOMER_NUMBER = 3000;
    	private final static int DESK_NUMBER = 6;
    
    	public final int ITEM_DURATION_S_MIN = 3;
    	public final int ITEM_DURATION_S_MAX = 8;
    
    	public final CustomerFactory customerFactory = new CustomerFactory(this, CUSTOMER_NUMBER);
    
    	public final ArrayList<DeskReport> results = new ArrayList<DeskReport>(DESK_NUMBER);
    	
    	public void perform(){
    		ExecutorService executor = Executors.newFixedThreadPool(DESK_NUMBER);
    		for (int i = 1; i <= DESK_NUMBER; i++) {
    			executor.submit(new Desk(this, i));
    		}
    
    		executor.shutdown();
            try {
                executor.awaitTermination(20, TimeUnit.SECONDS);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
    	}
    	
    	public void printResult(){
    		int maxTimeS = 0;
    		int maxItems = 0;
    		int maxCustomers = 0;
    		
    		int minItems = Integer.MAX_VALUE;
    		int minCustomers = Integer.MAX_VALUE;
    		
    		for(DeskReport r : results){
    			if(r.getSpentTime() > maxTimeS){
    				maxTimeS = r.getSpentTime();
    			}
    			
    			if(r.getSoldItemCount() > maxItems){
    				maxItems = r.getSoldItemCount();
    			}
    			if(r.getSoldItemCount() < minItems){
    				minItems = r.getSoldItemCount();
    			}
    			
    			
    			if(r.getServedCustomerCount() > maxCustomers){
    				maxCustomers = r.getServedCustomerCount();
    			}
    			if(r.getServedCustomerCount() < minCustomers){
    				minCustomers = r.getServedCustomerCount();
    			}
    			
    		}
    		
    		Date date = new Date(maxTimeS * 1000L);
    		DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    		String dateFormatted = formatter.format(date);
    		
    		
    		System.out.println("---------------- RESULTS ----------------");
    		System.out.println(DESK_NUMBER + " desks served " + CUSTOMER_NUMBER + " customers in " + dateFormatted);
    		System.out.println("Troughput min ~ max:");
    		System.out.println(minItems + "\t~\t" + maxItems + " \titems/desk");
    		System.out.println(minCustomers + "\t~\t" + maxCustomers + "\tcustomers/desk");
    	}
    	
    	public static void main(String[] args) {
    		Simulation sim = new Simulation();
    		sim.perform();
    		sim.printResult();
    	}
    }
    public class CustomerFactory {
    
    	private Simulation simulation;
    	private int capacity = 0;
    	
    	public CustomerFactory(Simulation simulation, int capacity){
    		this.simulation = simulation;
    		this.capacity = capacity;
    	}
    
    	public synchronized Customer getInstanceWithRandomCapacity(){
    		if(capacity-- > 1){
    			return new Customer(this.simulation.getRandomIntInRangeEnclosed(1,20));
    		} else {
    			return null;
    		}
    	}
    	
    }
    
    public class Desk implements Runnable{
    	private Simulation s = null;
    	private int deskNo = 0;
    
    	private int servedCustomerCount = 0;
    	private int soldItemCount = 0;
    	private int spentTime = 0;
    	
    	public Desk(Simulation s, int deskNo) {
    		this.s = s;
    		this.deskNo = deskNo;
    	}
    	
    	public void run() {
    		System.out.println("Desk " + deskNo + " opening...");
    
    		Customer c = null;
    		while ((c = s.customerFactory.getInstanceWithRandomCapacity()) != null) {
    			servedCustomerCount++;
    			for(int i=c.getItemCount(); i>1; i--){
    				soldItemCount++;
    				spentTime += s.getRandomIntInRangeEnclosed(s.ITEM_DURATION_S_MIN, s.ITEM_DURATION_S_MAX);
    			}
    			//get short break after each customer ;)
    			sleep(Long.valueOf(s.getRandomIntInRangeEnclosed(s.ITEM_DURATION_S_MIN, s.ITEM_DURATION_S_MAX)));
    		}
    		
    		s.results.add(new DeskReport(deskNo, servedCustomerCount, soldItemCount, spentTime));
    		System.out.println("Desk " + deskNo + "\tclosing.\tcustomers " + servedCustomerCount + "\titems " + soldItemCount + "\ttime(s) " + spentTime);
    	}
    	
    	private void sleep(long ms){
    		try {
    			Thread.sleep(ms);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class DeskReport {
    	private int deskNo = 0;
    	private int servedCustomerCount = 0;
    	private int soldItemCount = 0;
    	private int spentTime = 0;
    	
    	public DeskReport(int deskNo, int servedCustomerCount, int soldItemCount, int spentTime){
    		this.deskNo = deskNo;
    		this.servedCustomerCount = servedCustomerCount;
    		this.soldItemCount = soldItemCount;
    		this.spentTime = spentTime;
    	}
    	
    	public int getDeskNo() {
    		return deskNo;
    	}
    
    	public int getServedCustomerCount() {
    		return servedCustomerCount;
    	}
    
    	public int getSoldItemCount() {
    		return soldItemCount;
    	}
    
    	public int getSpentTime() {
    		return spentTime;
    	}
    	
    }
    
    public class Customer{
    	private int itemCount = 0;
    	
    	public Customer(int itemCount){
    		this.itemCount = itemCount;
    	}
    	
    	public int getItemCount(){
    		return this.itemCount;
    	}
    }

    Симуляция примитивнейшая, демонстрирует скорее работу планировщика потоков, нежели магазина. Но если ее развить: смоделировать неравномерное "поступление" покупателей в магазин, очередь к кассам, случайный выбор кассы покупателем и т.д., можно узнать много интересного о работе магазинов. А пока, чтоб не было совсем уж бессмысленно, считается хоть какая-то примитивная статистика.
    Ответ написан
  • Нормализация БД. Зло или добро?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Нормализация ради нормализации - зло в подавляющем большинстве случаев! Нормализация, как часть продуманного проектирования или рефакторинга модели данных - однозначно добро. Структура БД должна быть, по возможности, оптимальной для запросов, выполняемых на ней приложением, а вовсе не соответствовать какой-то там нормальной форме :) Это "оптимально" может в каждом конкретном случае зависеть от кучи факторов, начиная от самих запросов и особенностей конкретной использованной СУБД, и вплоть до объемов доступной памяти и скорости обращения к диску.
    Ответ написан
  • Что такое замещение в ООП?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Полиморфизм - один из трех фундаментальных принципов ООП-парадигмы.

    Замещение (также "перекрытие" или "переопределение" методов) - общее название механизма, предоставляемого ЯП для поддержки применения этого принципа при проектировании иерархий классов.

    Конкретные детали реализации механизма могут отличаться, (как, например в Java и JS), но суть с т.з. ООП остается той же. А вот в С, например, такого механизма вообще нет, однако это не препятствует (просто не помогает!) писать объектно ориентированный код на этом языке.

    Так что, если под "замещением" понимается именно overriding, я бы не стал так широко отождествлять цель и средство ее достижения :)
    Ответ написан
  • Крупная компания или маленькая фирма?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Согласно вот этому, эта "большая контора" сильно похожа на большую мясорубку/соковыжималку :( Мое личное мнение: если условия в маленькой фирме устраивают, это будет во всех отношениях лучше. Тем более, что для будущей карьеры (после учебы) это никакой роли не играет, а за время учебы никакого "карьерного роста" все равно не будет - будет обыкновенный студенческий контракт.
    Главное, смотрите, чтоб была реальная возможность учиться, а не просто "занимать место".
    UPD: Если не устраивает качество маленькой фирмы (быдлокодерство), попробуйте поискать другую, побольше... студенческих позиций полно, в т.ч. и в приличных фирмах! Не нужно путать "имя" фирмы со своими будущими карьерными шансами... это конкретное имя повысит их, если Вы выживете там годик-два на позиции менеджера, а для позиции почти бесплатной низкоквалифицированной рабсилы (на которую Вы, собственно, туда собрались) все - с точностью до наоборот.
    Ответ написан
  • Что нужно для создания bluetooth браслета?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Посмотрел автомобиль Мерседес, но смутила цена. Возможно создать автомобиль, затратив 300-500 долларов?


    Как Вы думаете, если бы существовала такая возможность, что бы помешало воспользоваться ей производителям смутивших Вас браслетов?
    Ответ написан
  • С чего начать изучение программирования микропроцессоров?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    были занятия по азам программирование микропроцессоров, но толком не объясняли ничего.


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

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

    Если выберете второй вариант, начните с физики, схемотехники логических элементов и архитектуры / устройства микропроцессоров. Потом переходите к информатике, учите ассемблер, C и, возможно, VHDL. как можно быстрее купите себе плату (да хоть ту же Ардуину) и учитесь писать программы. Других путей к выздоровлению не существует.
    Ответ написан
  • C# to Java или Чего стоит выучить новый язык, зная прежний?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    Требование совершенно справедливое, т.к. зная один единственный язык стать хорошим (тем более, пригодным для должности ведущего) программистом просто невозможно. Как абсолютный минимум нужно знать:
    - ассемблер и устройство процессоров,
    - минимум один "взрослый" язык (C/C++/Pascal)
    - минимум один VM-ориентированный язык (C#/Java)

    Зная C#, выучить синтаксис Java - вопрос одного-двух дней, но научиться правильно писать на нем программы - это как минимум один-два серьезных проекта, т.е. годик-другой. Однако, не расстраивайтесь - после третьего языка "изучение" последующих уже практически не напрягает. А потом наступает состояние, когда "новых" языков не остается - есть лишь языки, которые еще не использовал... но если нужно - просто берешь и используешь, "изучая" их, практически, по ходу дела. Вот именно оно и есть признак пригодности для должности ведущего программиста.
    Ответ написан
  • Скажите, где ошибка в коде Java?

    pi314
    @pi314
    Президент Солнечной системы и окрестностей
    //Проверяем, не ЗАБЫЛ ли пользователь ввести свое имя?
    if (name == null || name.trim().isEmpty()) { ...


    такая "хитрая" проверка нужна, т.к. readLine() вполне может вернуть null, и тогда мы упадем по NPE на name.trim()

    В Джава сравнение строк делается так
    if (name.equals("Вася"))
    a name=="" сравнит объект name с другим, новым объектом типа String, со значением "" ... которые, разумеется, никогда не будут равны (вне зависимости от того, равны ли между собой ЗНАЧЕНИЯ строк), ибо это два разных объекта!
    Ответ написан