juan_gandhi: (Default)
Juan-Carlos Gandhi ([personal profile] juan_gandhi) wrote2007-09-12 07:42 am

conceptual problems with Java

First, as an illustration. Do you know what is the biggest problem with flowcharts? They are absolutely against any kind of functional or object-oriented development principles. Their impact on software development... it may have been more negative. If you think in the terms of flowcharts, your question is "what next" - which looks really ridiculous to any OOP- or FP-practicing developer.

Now Java.

Say, you have some kind of "base class" (e.g. Employee), and some kind of "subclass" (e.g. ArrogantEngineer). The subclass inherits some behavior from Employee, has some specific methods, and overrides some methods from its base class.

Fine. Does it help to communicate with other entities? We have several typical choices, "idioms":

  • singleton - base class contains a bunch of static references to external worlds; they are magically instantiated, using either synchronized keyword, or "double check locking" idiom, or a fashionable, since Java 5, holder class (see Bob Lee's blog for details)

  • factory - base class contains a static reference to a "factory" that produces references to other specific entities - this way we can decouple the other worlds from ours

  • locator - like in CORBA or EJB, every time an ArrogantEngineer looks for a mouse, it has to start at "root context", ask for a MouseFactory location, etc. Maybe you have to start with MouseMinistry, and go down. Every time you need to move a mouse. Because the mouse you own may have expired.

  • double dispatch - okay, you find your mouse, and make it move, but how does the mouse know if it is on the verge of its carpet? You ask it every time? This ic called micromanagement. You are not supposed to do that. The mouse should tell you. "Don't call us, we'll call you". The mouse does not know you are an ArrogantEngineer - but you do, and act accordingly.

  • constructor - or setup, or configuration, whatever. Each Employee, on initialization, receives from an upper class representative all that they need for their future functioning. How does the "upper class" know that? That's their job; they are something like EmployeeMinistry, and know everything about everyone. Or they delegate to ArrogantEngineerMinistry which knows their subjects better.



What kind of mental model is this? Feodalism, I think. This is the world as represented in the minds of... yes, in the minds of Arrogant Engineers. I mean, Software Engineers.

Professional architects, I mean architects in building industry, see the world differently. First, nothing moves for them. Nobody owns nobody. Things consist of other things, and encapsulation happens on several levels. There is no communication between opposite walls or between the roof and the floor. If such a communication happens, it is called a leak, and should be eliminated.

What kind of a program would such an imaginary architect write?

It would be one enclosing class; everything that happens in the program, happens in the context of that class. Let's call it Enterprise. If there are some facilities that are directly available to everybody, so they are. We can introduce internal classes, like Department - these classes contain a lot of data which they may or may not publish. But they do not have to name the outer scope, the scope of Enterprise. And so on; employees access the data visible to them in Department scope.

I'm not saying it is an ideal model; it is just a slightly better model.

The problem with it in Java is that of course nobody wants to stuff all the code inside one huge file. And once you put it in another file, oops, you loose it: Java does not have mixins (yet), and so you cannot have an inner class, with a scope in an enclosing class, stored in a separate file. That's bummer.

P.S. (9/2011): Scala's cake pattern solve the problem more or less exactly this way. We have no traits in Java, so we are out of luck.
nine_k: A stream of colors expanding from brain (Default)

[personal profile] nine_k 2007-09-12 04:23 pm (UTC)(link)
Question: "once you put it in another file, oops, you loose it" -- could you please explain this in more detail?

Note 1: If something is one huge building, do you need to lock it completely when you need to alter it slightly, e.g. to fix a leaking faucet?

Note 2 (a meta-note): There are no good and bad things; there are things used appropriately and not.

[identity profile] ivan-gandhi.livejournal.com 2007-09-12 05:21 pm (UTC)(link)
1. I have to explain it better.

See, there are no mixins in Java. So you cannot have an inner class outside your file.

I guess this explains my position on your Note 1.

[identity profile] exceeder.livejournal.com 2007-09-12 07:04 pm (UTC)(link)
The real question is, would there be mixins (I am all for it), how long until people start using it? See, the whole development process of serious software is based on a bunch of contracts - published APIs, interfaces etc. Down from PRD people start splitting the work and agree on certain connection points via inter-team agreements. Ideally someone has an overview of the process and at the end of initial talks has a skeleton of the future product - originally described as bunch of interfaces and such.

It was all good for enclosed systems with litle interaction between parts. Then distributed transactions, logging and reflection came along, people moved on to keep things in thread-local vars, intercept function calls, discover bean properties... all of a sudden, simple Java-interface like contracts turned into lawyerish descriptions with multiple clauses and couple of dimensions.

The point is - I love mixins; I don't know how to make people use them with my code so that they don't blow it. I will be thankful if you came across and would point me to such docs, like for Ruby or JavaScript.

[identity profile] atly.livejournal.com 2007-09-12 07:16 pm (UTC)(link)
под mixin вы что понимаете? Паттерн, реализуемый через множественное наследование реализаций, или просто возможность размещения одного класса в нескольких классах?..

[identity profile] atly.livejournal.com 2007-09-12 07:27 pm (UTC)(link)
в смысле, в нескольких файлах

[identity profile] exceeder.livejournal.com 2007-09-12 07:45 pm (UTC)(link)
Ни то и не другое. Injection of code with access to local context of calling code:
int sumUp()
{
  int sum = 0;
  mySqlClient.query("SELECT amount FROM things",{ sum += result.data[0] });
  return sum;
}

Такого плана, при этом sum доступается к локальному контексту вызвавшей функции, а result - к вызываемой.

[identity profile] exceeder.livejournal.com 2007-09-12 07:50 pm (UTC)(link)
Scratch that. Я абсолютно неправ. Это continuations.

[identity profile] atly.livejournal.com 2007-09-12 07:51 pm (UTC)(link)
это то что в c# 2.0 называется анонимными делегатами?

[identity profile] exceeder.livejournal.com 2007-09-12 08:25 pm (UTC)(link)
Строго говоря, в C# нет такой функциональности. Анонимные делегаты - это генераторы (http://en.wikipedia.org/wiki/Generator_%28computer_science%29). Генераторы можно реализовать с помощью continuations (http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%B4%D0%BE%D0%BB%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5).

А mixins - это примеси (http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%81%D1%8C_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29).

[identity profile] 109.livejournal.com 2007-09-14 09:53 pm (UTC)(link)
> в C# нет такой функциональности

в тройке есть. see 26.2 Extension methods (http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/csharp_3.0_specification.doc)

[identity profile] elder-george.livejournal.com 2007-09-16 08:15 am (UTC)(link)
AFAIK, extension methods - просто синтаксический сахар, позволяющий вызывать чужие статические методы "как свои". Поскольку это сахар, он существует только на время компиляции. Поскольку это именно статические методы, добавить к расширяемому объекту новые состояния можно только ручками (например, через словарик в классе-helper'е).
Классические же примеси (и особенно Traits (http://en.wikipedia.org/wiki/Trait_(abstract_type))) это позволяют.

[identity profile] 109.livejournal.com 2007-09-16 07:46 pm (UTC)(link)
очень мало есть вещей, которые нельзя назвать "синтаксическим сахаром". это дурацкое словосочетание значит просто, что что-то реализовано средствами языка. это всегда хорошо.

[identity profile] elder-george.livejournal.com 2007-09-17 03:53 am (UTC)(link)
Совершенно с Вами согласен, что "синтаксический сахар" - практически всегда штука полезная.
Хотел просто указать, что extension methods хотя и похожи на mixins, всё-таки полного набора их возможностей не предоставляют.

[identity profile] 109.livejournal.com 2007-09-17 06:28 am (UTC)(link)
согласен, но для настоящих миксинов нужно же множественное наследование реализаций, а с ним свои проблемы...

[identity profile] elder-george.livejournal.com 2007-09-16 07:51 am (UTC)(link)
Извините, но, боюсь, Вы не совсем правы.
Анонимные делегаты - это closures (http://en.wikipedia.org/wiki/Closure), т.е. как замыкание функции с ее окружением. Замыкания в большинстве систем сводимы к классам (и наоборот).
Код типа
int sumUp()
{
int sum = 0;
mySqlClient.query("SELECT amount FROM things", delegate(QueryResult result){ sum += result.data[0] });
return sum;
}
будет скомпилирован в что-то вроде
class QueryResultHandler { // название другое, конечно
public int sum;
public void Handler(QueryResult result){ sum += result.data[0]; }
}
int sumUp(){
QueryResultHandler handler = new QueryResultHandler();
mySqlClient.Query("SELECT amount FROM things",handler.Handler);
return handler.sum;
}
Генераторам в C# соответствуют итераторы, т.е. реализации интерфейса IEnumerator (или IEnumerable). Они инкапсулируют конечный автомат, который возвращает значение в зависимости от своего состояния.
Т.е. если мы описываем метод вида
public IEnumerator EnumNumbers(int lowerLimit, int upperLimit){
    for(int i = lowerLimit; i < upperLimit; i++)
         yield return i;
}

у нас будет сгенерирован inner class, реализующий IEnumerator с полями i, state и current (названия, ес-сно, другие), а в IEnumerator.MoveNext() будет осуществляться инкремент i, его запись в current для пользователя и переключение состояния. Короче, достаточно мудрёные действия, которые при ручном кодировании могли бы быть оптимальней =)
При наличии в языке first class continuations проще реализовать генераторы, чем при наличии генераторов реализовать continuations (хотя это to some extent возможно, и об этом была статья на RSDN).
Еще при помощи итераторов можно реализовать ленивые вычисления, но это уже другая песня...

[identity profile] ivan-gandhi.livejournal.com 2007-09-12 08:51 pm (UTC)(link)
В общем смысле это - возможность а) разбить класс на несколько файлов; б) добавлять "декорации" к классу, загружая файлы с дополнительными членами и методами - даже перегружая имеющиеся методы (что можно считать аяяй... но ведь методы можно объявить final).

Что я на считаю нужным - всего лишь возможность разбивать класс на много файлов. Скажем:

file 1. chessgame.java
 class ChessGame {
   class Board;
   class Player;
   class Rules;
   class Figure;
(etc)
}

file 2. chessboard.java

class ChessGame {
  class Board {
    class Position;
    Map<Figure,Position> currentState;
(etc)
}

file 3. chessposition.java
class ChessGame {
  class Board {
    class Position {
  (etc)
}

[identity profile] selfmade.livejournal.com 2007-09-17 04:49 am (UTC)(link)
В C# 2.0 реализуется с помощью partial class, либо mixin (тот, который добавляет методы или интерфейсы в рантайме через Emit, т.е. почти assembler).

[identity profile] selfmade.livejournal.com 2007-09-17 04:50 am (UTC)(link)
Ой, Тут уже подсказали.

Звиняйте, с отпуска мы, расслабились. :)
nine_k: A stream of colors expanding from brain (Default)

[personal profile] nine_k 2007-09-12 07:57 pm (UTC)(link)
Thanks. The idea of inner classes does explain a lot.

[identity profile] 109.livejournal.com 2007-09-14 09:41 pm (UTC)(link)
vp meant "lose it". полный аналог "извени".

[identity profile] 109.livejournal.com 2007-09-14 09:40 pm (UTC)(link)
чо, у вас partial class declarations нету? 8-О

[identity profile] ivan-gandhi.livejournal.com 2007-09-15 02:12 am (UTC)(link)
Дык. А у вас есть? Бля. Ну извени. Что делать-то теперь? В вашинктонщину податься? У вас ведь там дожди сплошные... как я слышал.

[identity profile] 109.livejournal.com 2007-09-15 08:36 am (UTC)(link)
да зачем. ты там ваших убеди на сишарпе писать. а дожди тут в основном зимой.