Hacker Newsnew | past | comments | ask | show | jobs | submit | more zapov's commentslogin

While I like DDD very much (created much tooling over last 10 years to help develop software in such a way), but if you move outside of useful implementations, you don't end up with much. Talking to domain experts, analyzing your domain... that's just a straw man arguments to sell DDD. Ubiquitous language is a good argument for DDD, but I don't see that practised a lot. There is often a noticeable disconnect between how experts talk about the system and the abstractions in the system which represent them.

Also, on technical level, while there are a lot of useful things in DDD (aggregate roots, value objects, repositories, ...) there is also a cargo-cult like notion what is a good way to develop software. And when you listen to "the experts" you often get a feeling they can fake the talk, but surely don't know how to walk.

My single question to see if someone is practicing DDD is: do you refactor your codebase on deeper insights? I'm yet to see someone say yes to that. Often you get excuses not to touch code which is working since refactoring large codebase is impractical/risky.


I refactor my code fairly regularly (as specifications change). The use of TDD, DDD, CQRS and Event Sourcing gives me immense flexibility to be able to refactor a large codebase and then test it through its whole lifespan (with actual data).


> The use of TDD, DDD, CQRS and Event Sourcing gives me immense flexibility to be able to refactor a large codebase and then test it through its whole lifespan (with actual data).

What is your experience in applying those principles in a team? It would be very interesting to get some insight on it.


1. TDD is simple enough. Everyone should be doing it. 2. DDD - this usually results in plenty of healthy debates on naming conventions. Acronyms are abhorred and we try to agree with the stakeholders on the meaning of each word they use. 3. CQRS and Event Sourcing - this has required our team quite a bit more of startup time than a CRUD application would have. We have been lucky to have a very understanding Product Owner who gives us plenty of time to deal with tech debt. Although single features may have originally taken us longer (than the time it would have taken to do the same with CRUD) at the start of the project, years on this time and the complexity of refactoring or adding features has not really increased, as any functionality is contained within its bounded context.

The biggest difficulty has been explaining what we are doing and why to senior management. But we haven't had any bad incidents so far, so I think they like us.


Do you do full-blown event sourcing or apply it to specific areas only? If the latter, how do you decide which? How do you deal with performance? Specialized database (e.g. Event Store) or not?

Real life success stories about ES are rare, so I'd love to get more insight in the anatomy of the solution (way beyond these few questions). Blog post request, I guess.


We have full-blown event sourcing for pretty much everything. The performance on the read side is great (obviously). We have an Event Store and we rebuild the Domain for every new command, so it isn't particularly fast, but we have a situation where commands are only issued a few times every year by a single person, whereas there are millions of reads every day (hence justifying CQRS as a solution). We have a mixed solution around replaying events though, largely around the issues we have with file uploads. Every file upload triggers multiple events (uploaded, processed etc) and we have different solutions for different files. Small files we store in the events as a blob, whereas big file events upload the data to a projection store and will not be replayed, so we don't have the issue of having to keep the original files forever as well as the database. I should probably write a blog post about the project at some point, but I'd like to investigate with my bosses as to how much I can actually reveal about the domain (because it would make the read so much more interesting if I could say everything).


> My single question to see if someone is practicing DDD is: do you refactor your codebase on deeper insights?

I've been wanting to do this for a long time, I've devoted a lot of thought to working out when and how to perform these refactorings. But the reality is, business concerns drive the development of software, not the other way around.

The big reason why refactoring is needed is technical debt, not because the vision of the project changes. You have to get the code clean and well-designed before you'll be able to easily have insights about it. It's all a team can do to chip away at the debt slowly over time barring a bunch of resources devoted to a big cleanup.

In order to make insight-driven refactoring work, you first need to finish cleaning up your debt. Otherwise whenever you try to get started, the debt will get in your way and you'll start yak-shaving until another feature request or bug pops up.

Debt cleanup never gets finished, so refactoring on the basis of insight never gets done either.


Well thats kind of to the point. DDD is all about investing into your core domain since that gives you a business advantage.

In reality domain experts are not available (if existant at all). You implement features in shortest path possible and most of the time never really refactor. Gap between domain and implementation widens... and if you are lucky at one point decide on rewrite which only works if your devs became domain experts themselves.

My solution to that problem is to write software with tools which make refactoring cheap and it's kind of working for me.


> My solution to that problem is to write software with tools which make refactoring cheap and it's kind of working for me.

That. This is how much of a silver bullet as we have had since Brooks wrote his book... Except that it is older, was just kind of forgotten by that time.


> My solution to that problem is to write software with tools which make refactoring cheap and it's kind of working for me.

Relevant link posted a couple of days ago, to optimize for deletion rather than refactoring: https://vimeo.com/108441214.


Abstractions and libraries are surely not the problem. The higher the abstraction the more opportunity for high level optimizations. And they always trump low level optimizations.

The problems are that people dont know how to optimize things or are blocked by imposed architecture.


For JVM most popular benchmark is https://github.com/eishay/jvm-serializers/wiki


They are probably dissatisfied with developer stance toward their RAD framework.

I'm sure various business apps can be built successfully on top of their Visual programming IDE, but even Microsoft has mostly abandoned that route.

But I dislike that even they propagate the lie that systems are slow when built on top of "High level language". That is mostly an optimization problem and you can often optimize well beyond what people would be willing to do in lower level language.


Too bad they didnt use DSL JSON instead of Jackson for JSON test. They would probably edge top C ones then.


What's DSL JSON?



dsl-json looks like an interesting tool. " DSL compiler requires Mono/.NET, but only during compilation. There is no runtime Mono/.NET dependency, only JVM. "


Easy there tiger ;)

What does it even mean that something is string based?

Here: https://github.com/eishay/jvm-serializers/wiki a JVM bench where JSON is pretty competitive with binary formats [and results would be event better if project owners actually merged PRs ;( ]


I actually find compilers for transformation of DSL AST to target languages much more costly then designing the DSL syntax.

But that's probably because I don't think using templates for code generation is good enough. At least if you want to do something interesting with it.

Language workbenches cut down the cost of DSL design to minimum, but more interesting problem is providing valuable output from it.


> I actually find compilers for transformation of DSL AST to target languages much more costly then designing the DSL syntax.

Mind explaining why? What can be costly and complex in a chain of trivial transforms, each being very simple, flat and comprehensible?


When I say DSL I mean external DSL, not a fluent interface.

So an example of the problem I deal with is a database migration. Let's say we have an entity with a value

entity SqlTable { List<TableColumn> nestedTuple; }

value TableColumn { int i; }

and if I change column type in value object to long I want my compilers to prepare a DB migration with the appropriate SQL statements for the specific DB I use. Of course, there is nothing too complex about it, but it's not trivial either (in this case you have to prepare a second field, unnest the whole hierarchy to get to the nested field, copy it to new type and compact the hierarchy back again).

I find it costly since there are gazillion of such features. And when they start interacting with each other things gets messy.


> When I say DSL I mean external DSL, not a fluent interface

If you're using a meta-language, there is no difference between external and embedded DSLs. External (or standalone) DSLs also should be built exactly the same way, on top of a hierarchy of existing DSL components.

In your case, you're likely not compartmentalising your DSLs properly, trying to stuff too much functionality into a single DSL while it must be a chain of different DSLs. E.g., one DSL for describing a schema of the DB you want to migrate (with a tool for inferring it from the existing DB schema), another for representing the intermediate uniform data format and transforms over it, and a third for mapping the uniform intermediate representation on your target DB schema. Of course I do not know any details of your particular problem, just describing how I solved a DB migration problem before. Your specifics could add more to the DSL chain design.


But I find it highly valuable to have a single model representation as a source of truth. You can see how it works in practice here: https://github.com/ngs-doo/revenj

Also, there are no tools for describing DB schemas that way (except if you consider DB DDL such a schema). So my DSL is used as uniform data format. And it's not a problem of mapping between formats, but within the logic required to do such a mapping. It can't be expressed as a simple transformation, compiler is required to analyze and transform it appropriately in various scenarios. And if you want optimizations, good luck with "simple mapping".

So yeah, it's complicated, but it needs to be complicated to support simple modeling DSL. Otherwise you are better off with having several DB schemas, various POOs, Protobuf/Flatbuffer IDL etc...


In this case you need four DSLs - your core model and three DSLs for mapping the model to the specific storage backends.


> When I say DSL I mean external DSL, not a fluent interface.

That's the problem here. 'DSL' is a vague and ambiguous notion. An ad-hoc 'fluent interface' usually isn't considered a DSL.


I'm talking about efficiently compiled embedded DSLs built on top of meta-language hosts (with potentially more than one backend).


Do you plan on improving Protobuf speed in Java? People don't expect it to be slower than JSON ;)

http://hperadin.github.io/jvm-serializers-report/report.html


I'm not super familiar with the Java implementation, but I believe it's pretty optimized and appears to do very well generally on that benchmark.

One unavoidable issue is that, unlike JSON, protobuf serializers have to do two passes over the message tree, because in protobuf binary format all submessages are prefixed by their length. The first pass just calculates lengths, while the second performs the actual serialization. This could potentially slow down serialization compared to JSON, especially for message trees with lots of nodes/depth.


So encode from back to front? Then when you reach the front you know the length.


Interesting idea, and could be interesting to experiment with.

There are a lot of practical challenges though -- to provide a useful API you'd have to reverse the string at the end, since socket APIs don't generally provide streaming "WriteReverse" functions, and for good reason, because it would force them to buffer arbitrary amounts of data.

So we'd have to reverse the entire string at the end. The question is whether this would be cheaper than doing a second pass over the message tree. And also keep in mind that you would need the first pass to decode everything -- including UTF-8 data -- in reverse. But since the UTF-8 APIs for Java strings probably don't support this, you'd probably have to encode it, then reverse it to put it in the encoding buffer. That way when it gets reversed again at the end, it would be proper UTF-8.

At the end of the day, this probably wouldn't end up faster than what we do now. But can't say for sure without trying!


Reversing the output didn't come up when I did this sort of thing in C (for a different format): you can fill a buffer from the end, then just write the tail. But I guess Java does stick you with that? And I didn't have to deal with encoding to UTF-8 (ouch), or whatever other complications you might face, like streaming. Oh well! Hope the suggestion was stimulating anyway.


You can use JSON only as codec, which can give you performance of Protobuf with much better debugability.


As someone with a "similar" platform, I too am rather surprised this end up on HN frontpage ;(

Few questions:

* how is your editor different from MPS (except being browser based)?

* how does your project compares to an implementation on top of language workbenches?

* do you think your assumption about time spent on a project is mostly Haskell related or is that for some specific types of projects?

* are you thinking about implementing some framework of your own or do you have some other in mind?

* do you plan on integrating with existing libraries or write your own implementation?

And comments:

* for me good IDE feels like semantic editor. I'm inclined to believe that text based editor can have all the good features of semantic editor and avoid most of the bad ones.

* while writing simple structures one time and reusing them vertically in a project is useful, it's doubtful that it's worth while. It becomes worth while only if you have project in multiple languages/technologies. But mostly if you can do refactoring automatically (even database schema migrations).

* try to explain your project better, this should help you with narrowing it's scope. Most of the people will try to fit it into some category they are familiar with so emphasize the distinctions.

Good luck! ;)


Here's the link to MPS for those who don't already know what it is: https://www.jetbrains.com/mps/


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: